aboutsummaryrefslogtreecommitdiffstats
path: root/share/qtcreator
diff options
context:
space:
mode:
Diffstat (limited to 'share/qtcreator')
-rw-r--r--share/qtcreator/debugger/cdbbridge.py161
-rw-r--r--share/qtcreator/debugger/dumper.py2816
-rw-r--r--share/qtcreator/debugger/gdbbridge.py656
-rw-r--r--share/qtcreator/debugger/lldbbridge.py606
-rw-r--r--share/qtcreator/debugger/qttypes.py68
5 files changed, 2208 insertions, 2099 deletions
diff --git a/share/qtcreator/debugger/cdbbridge.py b/share/qtcreator/debugger/cdbbridge.py
index b5fc683cba..4ac053eb55 100644
--- a/share/qtcreator/debugger/cdbbridge.py
+++ b/share/qtcreator/debugger/cdbbridge.py
@@ -75,6 +75,13 @@ class Dumper(DumperBase):
self.outputLock = threading.Lock()
self.isCdb = True
+ #FIXME
+ typeid = self.typeid_for_string('@QVariantMap')
+ del self.type_code_cache[typeid]
+ del self.type_target_cache[typeid]
+ del self.type_size_cache[typeid]
+ del self.type_alignment_cache[typeid]
+
def enumValue(self, nativeValue):
val = nativeValue.nativeDebuggerValue()
# remove '0n' decimal prefix of the native cdb value output
@@ -117,6 +124,7 @@ class Dumper(DumperBase):
elif not nativeValue.type().resolved and nativeValue.type().code() == TypeCode.Struct and not nativeValue.hasChildren():
val.ldisplay = self.enumValue(nativeValue)
val.isBaseClass = val.name == nativeValue.type().name()
+ val.typeid = self.from_native_type(nativeValue.type())
val.nativeValue = nativeValue
val.laddress = nativeValue.address()
val.lbitsize = nativeValue.bitsize()
@@ -137,14 +145,10 @@ class Dumper(DumperBase):
for f in nativeType.fields()])
return typeId
- def nativeValueType(self, nativeValue):
- return self.fromNativeType(nativeValue.type())
-
- def fromNativeType(self, nativeType):
+ def from_native_type(self, nativeType):
self.check(isinstance(nativeType, cdbext.Type))
- typeId = self.nativeTypeId(nativeType)
- if self.typeData.get(typeId, None) is not None:
- return self.Type(self, typeId)
+ typeid = self.typeid_for_string(self.nativeTypeId(nativeType))
+ self.type_nativetype_cache[typeid] = nativeType
if nativeType.name().startswith('void'):
nativeType = FakeVoidType(nativeType.name(), self)
@@ -154,70 +158,61 @@ class Dumper(DumperBase):
if nativeType.name().startswith('<function>'):
code = TypeCode.Function
elif nativeType.targetName() != nativeType.name():
- return self.createPointerType(nativeType.targetName())
+ return self.create_pointer_typeid(self.typeid_for_string(nativeType.targetName()))
if code == TypeCode.Array:
# cdb reports virtual function tables as arrays those ar handled separetly by
# the DumperBase. Declare those types as structs prevents a lookup to a
# none existing type
if not nativeType.name().startswith('__fptr()') and not nativeType.name().startswith('<gentype '):
- targetName = nativeType.targetName()
- count = nativeType.arrayElements()
- if targetName.endswith(']'):
- (prefix, suffix, inner_count) = self.splitArrayType(targetName)
- type_name = '%s[%d][%d]%s' % (prefix, count, inner_count, suffix)
- else:
- type_name = '%s[%d]' % (targetName, count)
- tdata = self.TypeData(self, typeId)
- tdata.name = type_name
- tdata.code = TypeCode.Array
- tdata.ltarget = targetName
- tdata.lbitsize = lambda: nativeType.bitsize()
- return self.Type(self, typeId)
+ targetName = nativeType.targetName().strip()
+ self.type_name_cache[typeid] = nativeType.name()
+ self.type_code_cache[typeid] = code
+ self.type_target_cache[typeid] = self.typeid_for_string(targetName)
+ self.type_size_cache[typeid] = nativeType.bitsize() // 8
+ return typeid
code = TypeCode.Struct
- tdata = self.TypeData(self, typeId)
- tdata.name = nativeType.name()
- tdata.lbitsize = lambda: nativeType.bitsize()
- tdata.code = code
- tdata.moduleName = lambda: nativeType.module()
- if code == TypeCode.Struct:
- tdata.lfields = lambda value: \
- self.listFields(nativeType, value)
- tdata.lalignment = lambda: \
- self.nativeStructAlignment(nativeType)
- tdata.enumDisplay = lambda intval, addr, form: \
+ self.type_name_cache[typeid] = nativeType.name()
+ self.type_size_cache[typeid] = nativeType.bitsize() // 8
+ self.type_code_cache[typeid] = code
+ self.type_modulename_cache[typeid] = nativeType.module()
+ self.type_enum_display_cache[typeid] = lambda intval, addr, form: \
self.nativeTypeEnumDisplay(nativeType, intval, form)
- tdata.templateArguments = lambda: \
- self.listTemplateParameters(nativeType.name())
- return self.Type(self, typeId)
+ return typeid
- def listNativeValueChildren(self, nativeValue):
+ def listNativeValueChildren(self, nativeValue, include_bases):
+ fields = []
index = 0
nativeMember = nativeValue.childFromIndex(index)
while nativeMember:
+ # Why this restriction to things with address? Can't nativeValue
+ # be e.g. located in registers, without address?
if nativeMember.address() != 0:
- yield self.fromNativeValue(nativeMember)
+ if include_bases or nativeMember.name() != nativeMember.type().name():
+ field = self.fromNativeValue(nativeMember)
+ fields.append(field)
index += 1
nativeMember = nativeValue.childFromIndex(index)
+ return fields
- def listValueChildren(self, value):
+ def listValueChildren(self, value, include_bases=True):
nativeValue = value.nativeValue
if nativeValue is None:
nativeValue = cdbext.createValue(value.address(), self.lookupNativeType(value.type.name, 0))
- return self.listNativeValueChildren(nativeValue)
+ return self.listNativeValueChildren(nativeValue, include_bases)
- def listFields(self, nativeType, value):
+ def nativeListMembers(self, value, native_type, include_bases):
nativeValue = value.nativeValue
if nativeValue is None:
- nativeValue = cdbext.createValue(value.address(), nativeType)
- return self.listNativeValueChildren(nativeValue)
+ nativeValue = cdbext.createValue(value.address(), native_type)
+ return self.listNativeValueChildren(nativeValue, include_bases)
def nativeStructAlignment(self, nativeType):
#DumperBase.warn("NATIVE ALIGN FOR %s" % nativeType.name)
def handleItem(nativeFieldType, align):
- a = self.fromNativeType(nativeFieldType).alignment()
+ a = self.type_alignment(self.from_native_type(nativeFieldType))
return a if a > align else align
align = 1
for f in nativeType.fields():
@@ -398,20 +393,6 @@ class Dumper(DumperBase):
else:
return typeName
- def lookupType(self, typeNameIn, module=0):
- if len(typeNameIn) == 0:
- return None
- typeName = self.stripQintTypedefs(typeNameIn)
- if self.typeData.get(typeName, None) is None:
- nativeType = self.lookupNativeType(typeName, module)
- if nativeType is None:
- return None
- _type = self.fromNativeType(nativeType)
- if _type.typeId != typeName:
- self.registerTypeAlias(_type.typeId, typeName)
- return _type
- return self.Type(self, typeName)
-
def lookupNativeType(self, name, module=0):
if name.startswith('void'):
return FakeVoidType(name, self)
@@ -439,9 +420,6 @@ class Dumper(DumperBase):
ptr = cdbext.getAddressByName(type.name + '::staticMetaObject')
return ptr
- def warn(self, msg):
- self.put('{name="%s",value="",type="",numchild="0"},' % msg)
-
def fetchVariables(self, args):
self.resetStats()
(ok, res) = self.tryFetchInterpreterVariables(args)
@@ -458,13 +436,17 @@ class Dumper(DumperBase):
self.anonNumber = 0
variables = []
- for val in cdbext.listOfLocals(self.partialVariable):
- dumperVal = self.fromNativeValue(val)
- dumperVal.lIsInScope = dumperVal.name not in self.uninitialized
- variables.append(dumperVal)
+ try:
+ for val in cdbext.listOfLocals(self.partialVariable):
+ dumperVal = self.fromNativeValue(val)
+ dumperVal.lIsInScope = dumperVal.name not in self.uninitialized
+ variables.append(dumperVal)
- self.handleLocals(variables)
- self.handleWatches(args)
+ self.handleLocals(variables)
+ self.handleWatches(args)
+ except Exception:
+ t,v,tb = sys.exc_info()
+ self.showException("FETCH VARIABLES", t, v, tb)
self.put('],partial="%d"' % (len(self.partialVariable) > 0))
self.put(',timings=%s' % self.timings)
@@ -485,9 +467,6 @@ class Dumper(DumperBase):
def findValueByExpression(self, exp):
return cdbext.parseAndEvaluate(exp)
- def nativeDynamicTypeName(self, address, baseType):
- return None # Does not work with cdb
-
def nativeValueDereferenceReference(self, value):
return self.nativeValueDereferencePointer(value)
@@ -518,7 +497,7 @@ class Dumper(DumperBase):
else:
val = self.Value(self)
val.laddress = value.pointer()
- val._type = DumperBase.Type(self, value.type.targetName)
+ val.typeid = self.typeid_for_string(value.type.targetName)
val.nativeValue = value.nativeValue
return val
@@ -540,14 +519,11 @@ class Dumper(DumperBase):
res = self.nativeParseAndEvaluate(symbolName)
return None if res is None else res.address()
- def putItemX(self, value):
- #DumperBase.warn('PUT ITEM: %s' % value.stringify())
+ def putItem(self, value: DumperBase.Value):
typeobj = value.type # unqualified()
typeName = typeobj.name
- self.addToCache(typeobj) # Fill type cache
-
if not value.lIsInScope:
self.putSpecialValue('optimizedout')
#self.putType(typeobj)
@@ -571,8 +547,7 @@ class Dumper(DumperBase):
return
self.putAddress(value.address())
- if value.lbitsize is not None:
- self.putField('size', value.lbitsize // 8)
+ self.putField('size', self.type_size(value.typeid))
if typeobj.code == TypeCode.Function:
#DumperBase.warn('FUNCTION VALUE: %s' % value)
@@ -738,7 +713,7 @@ class Dumper(DumperBase):
#DumperBase.warn('INAME: %s' % self.currentIName)
if self.autoDerefPointers:
# Generic pointer type with AutomaticFormat, but never dereference char types:
- if value.type.targetName not in (
+ if value.type.targetName.strip() not in (
'char',
'signed char',
'int8_t',
@@ -769,7 +744,7 @@ class Dumper(DumperBase):
def putCStyleArray(self, value):
arrayType = value.type
- innerType = arrayType.ltarget
+ innerType = arrayType.target()
address = value.address()
if address:
self.putValue('@0x%x' % address, priority=-1)
@@ -783,7 +758,7 @@ class Dumper(DumperBase):
p = value.address()
if displayFormat != DisplayFormat.Raw and p:
- if innerType.name in (
+ if innerType.name.strip() in (
'char',
'int8_t',
'qint8',
@@ -828,7 +803,7 @@ class Dumper(DumperBase):
innerSize = innerType.size()
self.putNumChild(n)
#DumperBase.warn('ADDRESS: 0x%x INNERSIZE: %s INNERTYPE: %s' % (addrBase, innerSize, innerType))
- enc = innerType.simpleEncoding()
+ enc = self.type_encoding_cache.get(innerType.typeid, None)
maxNumChild = self.maxArrayCount()
if enc:
self.put('childtype="%s",' % innerType.name)
@@ -863,12 +838,8 @@ class Dumper(DumperBase):
if innerType in ('wchar_t', 'WCHAR'):
self.putType(typeName)
- charSize = self.lookupType('wchar_t').size()
- (length, data) = self.encodeCArray(ptr, charSize, limit)
- if charSize == 2:
- self.putValue(data, 'utf16', length=length)
- else:
- self.putValue(data, 'ucs4', length=length)
+ (length, data) = self.encodeCArray(ptr, 2, limit)
+ self.putValue(data, 'utf16', length=length)
return True
if displayFormat == DisplayFormat.Latin1String:
@@ -931,19 +902,12 @@ class Dumper(DumperBase):
self.putItem(derefValue)
self.currentChildType = savedCurrentChildType
- def extractPointer(self, value):
- code = 'I' if self.ptrSize() == 4 else 'Q'
- return self.extractSomething(value, code, 8 * self.ptrSize())
-
def createValue(self, datish, typish):
- if self.isInt(datish): # Used as address.
+ if isinstance(datish, int): # Used as address.
return self.createValueFromAddressAndType(datish, typish)
if isinstance(datish, bytes):
val = self.Value(self)
- if isinstance(typish, self.Type):
- val._type = typish
- else:
- val._type = self.Type(self, typish)
+ val.typeid = self.create_typeid(typish)
#DumperBase.warn('CREATING %s WITH DATA %s' % (val.type.name, self.hexencode(datish)))
val.ldata = datish
val.check()
@@ -952,11 +916,8 @@ class Dumper(DumperBase):
def createValueFromAddressAndType(self, address, typish):
val = self.Value(self)
- if isinstance(typish, self.Type):
- val._type = typish
- else:
- val._type = self.Type(self, typish)
+ val.typeid = self.create_typeid(typish)
val.laddress = address
if self.useDynamicType:
- val._type = val.type.dynamicType(address)
+ val.typeid = self.dynamic_typeid_at_address(val.typeid, address)
return val
diff --git a/share/qtcreator/debugger/dumper.py b/share/qtcreator/debugger/dumper.py
index 059bf7b23e..488f1e362e 100644
--- a/share/qtcreator/debugger/dumper.py
+++ b/share/qtcreator/debugger/dumper.py
@@ -3,7 +3,7 @@
import os
import codecs
-import collections
+import functools
import glob
import struct
import sys
@@ -31,11 +31,7 @@ except:
def hexencode_(s):
return ''.join(["%x" % c for c in s])
-if sys.version_info[0] >= 3:
- toInteger = int
-else:
- toInteger = long
-
+toInteger = int
class ReportItem():
"""
@@ -55,19 +51,6 @@ class ReportItem():
% (self.value, self.encoding, self.priority, self.length)
-class Timer():
- def __init__(self, d, desc):
- self.d = d
- self.desc = desc + '-' + d.currentIName
-
- def __enter__(self):
- self.starttime = time.time()
-
- def __exit__(self, exType, exValue, exTraceBack):
- elapsed = int(1000 * (time.time() - self.starttime))
- self.d.timings.append([self.desc, elapsed])
-
-
class Children():
def __init__(self, d, numChild=1, childType=None, childNumChild=None,
maxNumChild=None, addrBase=None, addrStep=None):
@@ -147,20 +130,28 @@ class UnnamedSubItem(SubItem):
class DumperBase():
@staticmethod
def warn(message):
- print('bridgemessage={msg="%s"},' % message.replace('"', '$').encode('latin1'))
+ print('bridgemessage={msg="%s"}' % message.replace('"', "'").replace('\\', '\\\\'))
- @staticmethod
- def showException(msg, exType, exValue, exTraceback):
- DumperBase.warn('**** CAUGHT EXCEPTION: %s ****' % msg)
+ #@staticmethod
+ def showException(self, msg, exType, exValue, exTraceback):
+ self.warn('**** CAUGHT EXCEPTION: %s ****' % msg)
try:
import traceback
- for line in traceback.format_exception(exType, exValue, exTraceback):
- DumperBase.warn('%s' % line)
+ for frame_desc in traceback.format_exception(exType, exValue, exTraceback):
+ for line in frame_desc.split('\n'):
+ self.warn(line)
except:
pass
- def timer(self, desc):
- return Timer(self, desc)
+ def dump_location(self):
+ import traceback
+ from io import StringIO
+ io = StringIO()
+ traceback.print_stack(file=io)
+ data = io.getvalue()
+ self.warn('LOCATION:')
+ for line in data.split('\n')[:-3]:
+ self.warn(line)
def __init__(self):
self.isCdb = False
@@ -185,7 +176,6 @@ class DumperBase():
self.passExceptions = False
self.isTesting = False
- self.typeData = {}
self.isBigEndian = False
self.packCode = '<'
@@ -197,6 +187,8 @@ class DumperBase():
self.dumpermodules = []
+ self.init_type_cache()
+
try:
# Fails in the piping case
self.dumpermodules = [
@@ -217,9 +209,10 @@ class DumperBase():
self.currentPrintsAddress = True
self.currentChildType = None
self.currentChildNumChild = None
- self.registerKnownTypes()
+ self.register_known_types()
def setVariableFetchingOptions(self, args):
+ self.last_args = args
self.resultVarName = args.get('resultvarname', '')
self.expandedINames = args.get('expanded', {})
self.stringCutOff = int(args.get('stringcutoff', 10000))
@@ -239,10 +232,25 @@ class DumperBase():
self.partialVariable = args.get('partialvar', '')
self.uninitialized = args.get('uninitialized', [])
self.uninitialized = list(map(lambda x: self.hexdecode(x), self.uninitialized))
- self.partialUpdate = int(args.get('partial', '0'))
- #DumperBase.warn('NAMESPACE: "%s"' % self.qtNamespace())
- #DumperBase.warn('EXPANDED INAMES: %s' % self.expandedINames)
- #DumperBase.warn('WATCHERS: %s' % self.watchers)
+ #self.warn('NAMESPACE: "%s"' % self.qtNamespace())
+ #self.warn('EXPANDED INAMES: %s' % self.expandedINames)
+ #self.warn('WATCHERS: %s' % self.watchers)
+
+ # Call this with 'py theDumper.profile1() from Creator
+ def profile(self):
+ '''Internal profiling'''
+ import cProfile
+ import visualize
+ profiler = cProfile.Profile()
+ profiler.enable()
+ self.profiled_command()
+ profiler.disable()
+ visualize.profile_visualize(profiler.getstats())
+
+ def profiled_command(self):
+ args = self.last_args
+ args['partialvar'] = ''
+ self.fetchVariables(args)
def setFallbackQtVersion(self, args):
version = int(args.get('version', self.fallbackQtVersion))
@@ -279,7 +287,6 @@ class DumperBase():
self.generalCache = {}
self.counts = {}
- self.structPatternCache = {}
self.timings = []
self.expandableINames = set({})
@@ -331,7 +338,7 @@ class DumperBase():
self.currentType = ReportItem()
def exitSubItem(self, item, exType, exValue, exTraceBack):
- #DumperBase.warn('CURRENT VALUE: %s: %s %s' %
+ #self.warn('CURRENT VALUE: %s: %s %s' %
# (self.currentIName, self.currentValue, self.currentType))
if exType is not None:
if self.passExceptions:
@@ -341,9 +348,9 @@ class DumperBase():
if not self.isCli:
try:
if self.currentType.value:
- typeName = self.currentType.value
- if len(typeName) > 0 and typeName != self.currentChildType:
- self.putField('type', typeName)
+ typename = self.currentType.value
+ if len(typename) > 0 and typename != self.currentChildType:
+ self.putField('type', typename)
if self.currentValue.value is None:
self.put('value="",encoding="notaccessible",numchild="0",')
else:
@@ -361,8 +368,8 @@ class DumperBase():
self.indent -= 1
try:
if self.currentType.value:
- typeName = self.currentType.value
- self.put('<%s> = {' % typeName)
+ typename = self.currentType.value
+ self.put('<%s> = {' % typename)
if self.currentValue.value is None:
self.put('<not accessible>')
@@ -388,14 +395,14 @@ class DumperBase():
self.currentType = item.savedType
return True
- def stripForFormat(self, typeName):
- if not isinstance(typeName, str):
- raise RuntimeError('Expected string in stripForFormat(), got %s' % type(typeName))
- if typeName in self.cachedFormats:
- return self.cachedFormats[typeName]
+ def stripForFormat(self, typename):
+ if not isinstance(typename, str):
+ raise RuntimeError('Expected string in stripForFormat(), got %s' % type(typename))
+ if typename in self.cachedFormats:
+ return self.cachedFormats[typename]
stripped = ''
inArray = 0
- for c in typeName:
+ for c in typename:
if c == '<':
break
if c == ' ':
@@ -407,59 +414,192 @@ class DumperBase():
if inArray and ord(c) >= 48 and ord(c) <= 57:
continue
stripped += c
- self.cachedFormats[typeName] = stripped
+ self.cachedFormats[typename] = stripped
return stripped
- def templateArgument(self, typeobj, position):
- return typeobj.templateArgument(position)
+ def templateArgument(self, typeobj, index):
+ return self.type_template_argument(typeobj.typeid, index)
def intType(self):
- result = self.lookupType('int')
- self.intType = lambda: result
- return result
+ return self.type_for_int
def charType(self):
- result = self.lookupType('char')
- self.charType = lambda: result
- return result
+ return self.type_for_char
def ptrSize(self):
result = self.lookupType('void*').size()
self.ptrSize = lambda: result
return result
- def lookupType(self, typeName):
- nativeType = self.lookupNativeType(typeName)
- return None if nativeType is None else self.fromNativeType(nativeType)
-
- def registerKnownTypes(self):
- tdata = self.TypeData(self, 'unsigned short')
- tdata.lbitsize = 16
- tdata.lalignment = 2
- tdata.code = TypeCode.Integral
+ def lookupType(self, typename):
+ if not isinstance(typename, str):
+ raise RuntimeError('ARG ERROR FOR lookupType, got %s' % type(typename))
+
+ typeid = self.typeid_for_string(typename)
+ native_type = self.type_nativetype_cache.get(typeid)
+ if native_type is None:
+ native_type = self.lookupNativeType(typename)
+ if native_type is None:
+ #sCANNOT DETERMINE SIZE FOR TYelf.dump_location()
+ self.dump_location()
+ self.warn("TYPEIDS: %s" % self.typeid_cache)
+ self.warn("COULD NOT FIND TYPE '%s'" % typename)
+ return None
- tdata = self.TypeData(self, 'QChar')
- tdata.lbitsize = 16
- tdata.lalignment = 2
- tdata.code = TypeCode.Struct
- tdata.lfields = [self.Field(dumper=self, name='ucs',
- type='unsigned short', bitsize=16, bitpos=0)]
- tdata.templateArguments = lambda: []
+ self.type_nativetype_cache[typeid] = native_type
+ typeid = self.from_native_type(native_type)
+ if typeid == 0:
+ return None
+ return self.Type(self, typeid)
+
+ def register_type(self, name, code, size, enc=None):
+ typeid = self.typeid_for_string(name)
+ self.type_code_cache[typeid] = code
+ self.type_size_cache[typeid] = size
+ self.type_alignment_cache[typeid] = size
+ if enc is not None:
+ self.type_encoding_cache[typeid] = enc
+ return typeid
+
+ def register_int(self, name, size, enc=None):
+ typeid = self.typeid_for_string(name)
+ self.type_code_cache[typeid] = TypeCode.Integral
+ self.type_size_cache[typeid] = size
+ self.type_alignment_cache[typeid] = size
+ if enc is not None:
+ self.type_encoding_cache[typeid] = enc
+ return typeid
+
+ def register_enum(self, name, size):
+ typeid = self.typeid_for_string(name)
+ self.type_code_cache[typeid] = TypeCode.Enum
+ self.type_size_cache[typeid] = size
+ self.type_alignment_cache[typeid] = size
+ return typeid
+
+ def register_typedef(self, name, target_typeid):
+ typeid = self.typeid_for_string(name)
+ self.type_code_cache[typeid] = TypeCode.Typedef
+ self.type_target_cache[typeid] = target_typeid
+ self.type_size_cache[typeid] = self.type_size_cache[target_typeid]
+ self.type_alignment_cache[typeid] = self.type_alignment_cache[target_typeid]
+ return typeid
+
+ def register_struct(self, name, p5=0, p6=0, s=0):
+ # p5 = n -> n * ptrsize for Qt 5
+ # p6 = n -> n * ptrsize for Qt 6
+ #if self.qtVersion() >= 0x060000: # FIXME: Qt 5, ptrSize()
+ size = 8 * p6 + s
+ typeid = self.typeid_for_string(name)
+ self.type_code_cache[typeid] = TypeCode.Struct
+ self.type_size_cache[typeid] = size
+ self.type_alignment_cache[typeid] = 8
+ return typeid
+
+ def register_known_types(self):
+ typeid = 0
+ self.typeid_cache[''] = typeid
+ self.type_code_cache[typeid] = TypeCode.Void
+ self.type_name_cache[typeid] = '<Error>'
+ self.type_size_cache[typeid] = 1
+
+ typeid_char = self.register_int('char', 1, 'uint:1')
+ self.type_for_char = self.Type(self, typeid_char)
+ self.register_int('signed char', 1, 'int:1')
+ self.register_int('unsigned char', 1, 'uint:1')
+ self.register_int('bool', 1, 'uint:1')
+ self.register_int('char8_t', 1, 'uint:1')
+ self.register_int('int8_t', 1, 'int:1')
+ self.register_int('uint8_t', 1, 'uint:1')
+ self.register_int('qint8', 1, 'int:1')
+ self.register_int('quint8', 1, 'uint:1')
+
+ self.register_int('short', 2, 'int:2')
+ self.register_int('short int', 2, 'int:2')
+ self.register_int('signed short', 2, 'int:2')
+ self.register_int('signed short int', 2, 'int:2')
+ typeid_unsigned_short = \
+ self.register_int('unsigned short', 2, 'uint:2')
+ self.register_int('unsigned short int', 2, 'uint:2')
+ self.register_int('char16_t', 2, 'uint:2')
+ self.register_int('int16_t', 2, 'int:2')
+ self.register_int('uint16_t', 2, 'uint:2')
+ self.register_int('qint16', 2, 'int:2')
+ self.register_int('quint16', 2, 'uint:2')
+
+ typeid_int = self.register_type('int', 4, 'int:4')
+ self.type_for_int = self.Type(self, typeid_int)
+ self.register_int('int', 4, 'int:4')
+ self.register_int('signed int', 4, 'int:4')
+ self.register_int('unsigned int', 4, 'uint:4')
+ self.register_int('char32_t', 4, 'int:4')
+ self.register_int('int32_t', 4, 'int:4')
+ self.register_int('uint32_t', 4, 'uint:4')
+ self.register_int('qint32', 4, 'int:4')
+ self.register_int('quint32', 4, 'uint:4')
+
+ self.register_int('long long', 8, 'int:8')
+ self.register_int('signed long long', 8, 'int:8')
+ self.register_int('unsigned long long', 8, 'uint:8')
+ self.register_int('int64_t', 8, 'int:8')
+ self.register_int('uint64_t', 8, 'uint:8')
+ self.register_int('qint64', 8, 'int:8')
+ self.register_int('quint64', 8, 'uint:8')
+
+ self.register_type('float', TypeCode.Float, 4, 'float:4')
+ typeid_double = self.register_type('double', TypeCode.Float, 8, 'float:8')
+ self.register_typedef('qreal', typeid_double)
+
+ typeid_qchar = self.register_type('@QChar', TypeCode.Struct, 2, 'uint:2')
+ #self.type_fields_cache[typeid_qchar] = [
+ # self.Field(name='ucs', typeid=typeid_unsigned_short, bitsize=16, bitpos=0)]
+
+ self.register_enum('@Qt::ItemDataRole', 4)
+
+ self.register_struct('@QObject', p5=2, p6=2)
+ self.register_struct('@QObjectPrivate', p5=10, p6=10) # FIXME: Not exact
+
+ self.register_struct('@QByteArray', p5=1, p6=3)
+ self.register_struct('@QString', p5=1, p6=3)
+ self.register_struct('@QStandardItemData', p5=3, p6=5)
+ self.register_struct('@QVariant', p5=2, p6=4)
+ self.register_struct('@QXmlAttributes::Attribute', p5=4, p6=12)
+
+ self.register_struct('@QList<@QObject*>', p5=1, p6=3)
+ self.register_struct('@QList<@QStandardItemData>', p5=1, p6=3)
+ self.register_struct('@QList<@QRect>', p5=1, p6=3)
+
+ typeid_var_list = self.register_struct('@QList<@QVariant>', p5=1, p6=3)
+ self.register_typedef('@QVariantList', typeid_var_list)
+
+ typeid_var_map = self.register_struct('@QMap<@QString, @QVariant>', p5=1, p6=1)
+ self.register_typedef('@QVariantMap', typeid_var_map)
+
+ typeid_var_hash = self.register_struct('@QHash<@QString, @QVariant>', p5=1, p6=1)
+ self.register_typedef('@QVariantHash', typeid_var_hash)
+
+ self.register_struct('@QPoint', s=8)
+ self.register_struct('@QPointF', s=16)
+ self.register_struct('@QLine', s=16)
+ self.register_struct('@QLineF', s=32)
+
+ # FIXME: Comment out for production, see [MARK_A]
+ name1 = 'std::__cxx11::basic_string<char,std::char_traits<char>,std::allocator<char>>'
+ self.register_struct(name1, p6=4)
def nativeDynamicType(self, address, baseType):
return baseType # Override in backends.
- def listTemplateParameters(self, typename):
- return self.listTemplateParametersManually(typename)
-
- def listTemplateParametersManually(self, typename):
+ def fill_template_parameters_manually(self, typeid):
+ typename = self.type_name(typeid)
# Undo id mangling for template typedefs. Relevant for QPair.
if typename.endswith('}'):
typename = typename[typename.find('{') + 1 : -1]
- targs = []
if not typename.endswith('>'):
- return targs
+ return
+
+ targs = []
def push(inner):
# Handle local struct definitions like QList<main(int, char**)::SomeStruct>
@@ -471,14 +611,14 @@ class DumperBase():
inner = inner[6:].strip()
if inner.endswith(' const'):
inner = inner[:-6].strip()
- #DumperBase.warn("FOUND: %s" % inner)
+ #self.warn("FOUND: %s" % inner)
targs.append(inner)
- #DumperBase.warn("SPLITTING %s" % typename)
+ #self.warn("SPLITTING %s" % typename)
level = 0
inner = ''
for c in typename[::-1]: # Reversed...
- #DumperBase.warn("C: %s" % c)
+ #self.warn("C: %s" % c)
if c == '>':
if level > 0:
inner += c
@@ -492,7 +632,7 @@ class DumperBase():
inner = ''
break
elif c == ',':
- #DumperBase.warn('c: %s level: %s' % (c, level))
+ #self.warn('c: %s level: %s' % (c, level))
if level == 1:
push(inner)
inner = ''
@@ -501,28 +641,34 @@ class DumperBase():
else:
inner += c
- #DumperBase.warn("TARGS: %s %s" % (typename, targs))
- res = []
+ #self.warn("TARGS: %s %s" % (typename, targs))
+ idx = 0
for item in targs[::-1]:
if len(item) == 0:
continue
- c = ord(item[0])
- if c in (45, 46) or (c >= 48 and c < 58): # '-', '.' or digit.
- if item.find('.') > -1:
- res.append(float(item))
- else:
- if item.endswith('l'):
- item = item[:-1]
- if item.endswith('u'):
- item = item[:-1]
- val = toInteger(item)
- if val > 0x80000000:
- val -= 0x100000000
- res.append(val)
+ if item == "false": # Triggered in StdTuple dumper
+ self.type_template_arguments_cache[(typeid, idx)] = False
+ elif item == "true":
+ self.type_template_arguments_cache[(typeid, idx)] = True
else:
- res.append(self.Type(self, item))
- #DumperBase.warn("RES: %s %s" % (typename, [(None if t is None else t.name) for t in res]))
- return res
+ c = ord(item[0])
+ if c in (45, 46) or (c >= 48 and c < 58): # '-', '.' or digit.
+ if '.' in item:
+ res.append(float(item))
+ else:
+ if item.endswith('l'):
+ item = item[:-1]
+ if item.endswith('u'):
+ item = item[:-1]
+ val = int(item)
+ if val > 0x80000000:
+ val -= 0x100000000
+ self.type_template_arguments_cache[(typeid, idx)] = val
+ else:
+ targ = self.Type(self, self.create_typeid_from_name(item))
+ self.type_template_arguments_cache[(typeid, idx)] = targ
+ idx += 1
+ #self.warn('MANUAL: %s %s' % (type_name, targs))
# Hex decoding operating on str, return str.
@staticmethod
@@ -619,7 +765,7 @@ class DumperBase():
(dummy, dummy, dummy, length) = self.split('IIIp', array_data_ptr)
length = self.extractInt(array_data_ptr + 3 * self.ptrSize()) & 0x3ffffff
alloc = length # pretend.
- data = self.extractPointer(array_data_ptr + self.ptrSize())
+ data = self.extract_pointer_at_address(array_data_ptr + self.ptrSize())
return data, length, alloc
def encodeStringHelper(self, value, limit):
@@ -666,14 +812,14 @@ class DumperBase():
displayFormat=DisplayFormat.Automatic,
makeExpandable=True):
charSize = charType.size()
- self.putCharArrayValue(data, size, charSize, displayFormat=displayFormat)
+ self.putCharArrayValue(data, size, charSize, displayFormat)
if makeExpandable:
self.putNumChild(size)
if self.isExpanded():
with Children(self):
for i in range(size):
- self.putSubItem(size, self.createValue(data + i * charSize, charType))
+ self.putSubItem(size, self.createValueFromAddress(data + i * charSize, charType))
def readMemory(self, addr, size):
return self.hexencode(bytes(self.readRawMemory(addr, size)))
@@ -699,39 +845,6 @@ class DumperBase():
def stringData(self, value): # -> (data, size, alloc)
return self.qArrayData(value)
- def extractTemplateArgument(self, typename, position):
- level = 0
- skipSpace = False
- inner = ''
- for c in typename[typename.find('<') + 1: -1]:
- if c == '<':
- inner += c
- level += 1
- elif c == '>':
- level -= 1
- inner += c
- elif c == ',':
- if level == 0:
- if position == 0:
- return inner.strip()
- position -= 1
- inner = ''
- else:
- inner += c
- skipSpace = True
- else:
- if skipSpace and c == ' ':
- pass
- else:
- inner += c
- skipSpace = False
- # Handle local struct definitions like QList<main(int, char**)::SomeStruct>
- inner = inner.strip()
- p = inner.find(')::')
- if p > -1:
- inner = inner[p + 3:]
- return inner
-
def putStringValue(self, value):
length, data = self.encodeStringHelper(value, self.displayStringLimit)
self.putValue(data, 'utf16', length=length)
@@ -750,10 +863,9 @@ class DumperBase():
self.putType('int')
def putEnumItem(self, name, ival, typish):
- buf = bytearray(struct.pack('i', ival))
val = self.Value(self)
- val.ldata = bytes(buf)
- val._type = self.createType(typish)
+ val.ldata = ival
+ val.typeid = self.create_typeid(typish)
with SubItem(self, name):
self.putItem(val)
@@ -826,15 +938,19 @@ class DumperBase():
def putSymbolValue(self, address):
self.putValue(self.prettySymbolByAddress(address))
- def putVTableChildren(self, item, itemCount):
- p = item.pointer()
+ def putVTableChildren(self, value, itemCount):
+ p = self.value_as_address(value)
+ entry_typeid = self.create_pointer_typeid(self.create_typeid('void'))
for i in range(itemCount):
- deref = self.extractPointer(p)
+ deref = self.extract_pointer_at_address(p)
if deref == 0:
itemCount = i
break
with SubItem(self, i):
- self.putItem(self.createPointerValue(deref, 'void'))
+ val = self.Value(self)
+ val.ldata = deref
+ val.typeid = entry_typeid
+ self.putItem(val)
p += self.ptrSize()
return itemCount
@@ -842,7 +958,9 @@ class DumperBase():
baseIndex = 0
for item in value.members(True):
if item.name is not None:
- if item.name.startswith('_vptr.') or item.name.startswith('__vfptr'):
+ if (item.name.startswith('_vptr.')
+ or item.name.startswith('_vptr$')
+ or item.name.startswith('__vfptr')):
with SubItem(self, '[vptr]'):
# int (**)(void)
self.putType(' ')
@@ -892,15 +1010,22 @@ class DumperBase():
def check(self, exp):
if not exp:
+ self.warn('Check failed: %s' % exp)
+ self.dump_location()
raise RuntimeError('Check failed: %s' % exp)
+ def check_typeid(self, typeid):
+ if not isinstance(typeid, int):
+ size = self.type_size_cache.get(typeid, None)
+ raise RuntimeError('WRONG TYPE FOR TYPEID: %s %s' % (str(typeid), type(typeid)))
+
def checkRef(self, ref):
# Assume there aren't a million references to any object.
self.check(ref >= -1)
self.check(ref < 1000000)
def checkIntType(self, thing):
- if not self.isInt(thing):
+ if not isinstance(thing, int):
raise RuntimeError('Expected an integral value, got %s' % type(thing))
def readToFirstZero(self, base, typesize, maximum):
@@ -919,7 +1044,7 @@ class DumperBase():
maximum = int(maximum / 2)
self.warn('REDUCING READING MAXIMUM TO %s' % maximum)
- #DumperBase.warn('BASE: 0x%x TSIZE: %s MAX: %s' % (base, typesize, maximum))
+ #self.warn('BASE: 0x%x TSIZE: %s MAX: %s' % (base, typesize, maximum))
for i in range(0, maximum, typesize):
t = struct.unpack_from(code, blob, i)[0]
if t == 0:
@@ -1039,11 +1164,14 @@ class DumperBase():
def putType(self, typish, priority=0):
# Higher priority values override lower ones.
if priority >= self.currentType.priority:
- types = (str) if sys.version_info[0] >= 3 else (str, unicode)
- if isinstance(typish, types):
+ if isinstance(typish, str):
self.currentType.value = typish
- else:
+ elif isinstance(typish, int):
+ self.currentType.value = self.type_name(typish)
+ elif isinstance(typish, self.Type):
self.currentType.value = typish.name
+ else:
+ self.currentType.value = str(type(typish))
self.currentType.priority = priority
def putValue(self, value, encoding=None, priority=0, length=None):
@@ -1095,23 +1223,26 @@ class DumperBase():
self.putItem(value)
def isExpanded(self):
- #DumperBase.warn('IS EXPANDED: %s in %s: %s' % (self.currentIName,
+ #self.warn('IS EXPANDED: %s in %s: %s' % (self.currentIName,
# self.expandedINames, self.currentIName in self.expandedINames))
return self.currentIName in self.expandedINames
- def mangleName(self, typeName):
+ def mangleName(self, typename):
return '_ZN%sE' % ''.join(map(lambda x: '%d%s' % (len(x), x),
- typeName.split('::')))
+ typename.split('::')))
- def arrayItemCountFromTypeName(self, typeName, fallbackMax=1):
- itemCount = typeName[typeName.find('[') + 1:typeName.find(']')]
+ def arrayItemCountFromTypeName(self, typename, fallbackMax=1):
+ itemCount = typename[typename.find('[') + 1:typename.find(']')]
return int(itemCount) if itemCount else fallbackMax
def putCStyleArray(self, value):
- arrayType = value.type.unqualified()
- innerType = arrayType.ltarget
+ arrayType = value.type
+ innerType = arrayType.target()
+ #self.warn("ARRAY TYPE: %s" % arrayType)
+ #self.warn("INNER TYPE: %s" % innerType)
if innerType is None:
- innerType = value.type.target().unqualified()
+ innerType = value.type.target()
+
address = value.address()
if address:
self.putValue('@0x%x' % address, priority=-1)
@@ -1161,19 +1292,19 @@ class DumperBase():
def cleanAddress(self, addr):
if addr is None:
return '<no address>'
- return '0x%x' % toInteger(hex(addr), 16)
+ return '0x%x' % int(hex(addr), 16)
- def stripNamespaceFromType(self, typeName):
+ def stripNamespaceFromType(self, typename):
ns = self.qtNamespace()
- if len(ns) > 0 and typeName.startswith(ns):
- typeName = typeName[len(ns):]
- # DumperBase.warn( 'stripping %s' % typeName )
+ if len(ns) > 0 and typename.startswith(ns):
+ typename = typename[len(ns):]
+ # self.warn( 'stripping %s' % typename )
lvl = 0
pos = None
stripChunks = []
- sz = len(typeName)
+ sz = len(typename)
for index in range(0, sz):
- s = typeName[index]
+ s = typename[index]
if s == '<':
lvl += 1
if lvl == 1:
@@ -1188,22 +1319,22 @@ class DumperBase():
if lvl != 0:
raise RuntimeError("unbalanced at end of type name")
for (f, l) in reversed(stripChunks):
- typeName = typeName[:f] + typeName[l:]
- return typeName
+ typename = typename[:f] + typename[l:]
+ return typename
- def tryPutPrettyItem(self, typeName, value):
+ def tryPutPrettyItem(self, typename, value):
value.check()
if self.useFancy and self.currentItemFormat() != DisplayFormat.Raw:
- self.putType(typeName)
+ self.putType(typename)
- nsStrippedType = self.stripNamespaceFromType(typeName)\
+ nsStrippedType = self.stripNamespaceFromType(typename)\
.replace('::', '__')
# Strip leading 'struct' for C structs
if nsStrippedType.startswith('struct '):
nsStrippedType = nsStrippedType[7:]
- #DumperBase.warn('STRIPPED: %s' % nsStrippedType)
+ #self.warn('STRIPPED: %s' % nsStrippedType)
# The following block is only needed for D.
if nsStrippedType.startswith('_A'):
# DMD v2.058 encodes string[] as _Array_uns long long.
@@ -1216,7 +1347,7 @@ class DumperBase():
return True
dumper = self.qqDumpers.get(nsStrippedType)
- #DumperBase.warn('DUMPER: %s' % dumper)
+ #self.warn('DUMPER: %s' % dumper)
if dumper is not None:
dumper(self, value)
return True
@@ -1242,15 +1373,15 @@ class DumperBase():
self.putField('editvalue', value)
# This is shared by pointer and array formatting.
- def tryPutSimpleFormattedPointer(self, ptr, typeName, innerType, displayFormat, limit):
+ def tryPutSimpleFormattedPointer(self, ptr, typename, innerType, displayFormat, limit):
if displayFormat == DisplayFormat.Automatic:
targetType = innerType
if innerType.code == TypeCode.Typedef:
- targetType = innerType.ltarget
+ targetType = innerType.target()
if targetType.name in ('char', 'signed char', 'unsigned char', 'uint8_t', 'CHAR'):
# Use UTF-8 as default for char *.
- self.putType(typeName)
+ self.putType(typename)
(length, shown, data) = self.readToFirstZero(ptr, 1, limit)
self.putValue(data, 'utf8', length=length)
if self.isExpanded():
@@ -1258,7 +1389,7 @@ class DumperBase():
return True
if targetType.name in ('wchar_t', 'WCHAR'):
- self.putType(typeName)
+ self.putType(typename)
charSize = self.lookupType('wchar_t').size()
(length, data) = self.encodeCArray(ptr, charSize, limit)
if charSize == 2:
@@ -1268,58 +1399,54 @@ class DumperBase():
return True
if displayFormat == DisplayFormat.Latin1String:
- self.putType(typeName)
+ self.putType(typename)
(length, data) = self.encodeCArray(ptr, 1, limit)
self.putValue(data, 'latin1', length=length)
return True
if displayFormat == DisplayFormat.SeparateLatin1String:
- self.putType(typeName)
+ self.putType(typename)
(length, data) = self.encodeCArray(ptr, 1, limit)
self.putValue(data, 'latin1', length=length)
self.putDisplay('latin1:separate', data)
return True
if displayFormat == DisplayFormat.Utf8String:
- self.putType(typeName)
+ self.putType(typename)
(length, data) = self.encodeCArray(ptr, 1, limit)
self.putValue(data, 'utf8', length=length)
return True
if displayFormat == DisplayFormat.SeparateUtf8String:
- self.putType(typeName)
+ self.putType(typename)
(length, data) = self.encodeCArray(ptr, 1, limit)
self.putValue(data, 'utf8', length=length)
self.putDisplay('utf8:separate', data)
return True
if displayFormat == DisplayFormat.Local8BitString:
- self.putType(typeName)
+ self.putType(typename)
(length, data) = self.encodeCArray(ptr, 1, limit)
self.putValue(data, 'local8bit', length=length)
return True
if displayFormat == DisplayFormat.Utf16String:
- self.putType(typeName)
+ self.putType(typename)
(length, data) = self.encodeCArray(ptr, 2, limit)
self.putValue(data, 'utf16', length=length)
return True
if displayFormat == DisplayFormat.Ucs4String:
- self.putType(typeName)
+ self.putType(typename)
(length, data) = self.encodeCArray(ptr, 4, limit)
self.putValue(data, 'ucs4', length=length)
return True
return False
- def putFormattedPointer(self, value):
- #with self.timer('formattedPointer'):
- self.putFormattedPointerX(value)
-
def putDerefedPointer(self, value):
- derefValue = value.dereference()
- innerType = value.type.target() # .unqualified()
+ derefValue = self.value_dereference(value)
+ innerType = value.type.target()
self.putType(innerType)
savedCurrentChildType = self.currentChildType
self.currentChildType = innerType.name
@@ -1332,47 +1459,47 @@ class DumperBase():
self.putItem(derefValue)
self.currentChildType = savedCurrentChildType
- def putFormattedPointerX(self, value):
+ def putFormattedPointer(self, value):
self.putOriginalAddress(value.address())
- #DumperBase.warn("PUT FORMATTED: %s" % value)
- pointer = value.pointer()
+ #self.warn("PUT FORMATTED: %s" % value)
+ pointer = self.value_as_address(value)
self.putAddress(pointer)
- #DumperBase.warn('POINTER: 0x%x' % pointer)
+ #self.warn('POINTER: 0x%x' % pointer)
if pointer == 0:
- #DumperBase.warn('NULL POINTER')
- self.putType(value.type)
+ #self.warn('NULL POINTER')
+ self.putType(value.typeid)
self.putValue('0x0')
return
- typeName = value.type.name
+ typename = self.type_name(value.typeid)
try:
self.readRawMemory(pointer, 1)
except:
# Failure to dereference a pointer should at least
# show the value of a pointer.
- #DumperBase.warn('BAD POINTER: %s' % value)
+ #self.warn('BAD POINTER: %s' % value)
self.putValue('0x%x' % pointer)
- self.putType(typeName)
+ self.putType(typename)
return
if self.currentIName.endswith('.this'):
self.putDerefedPointer(value)
return
- displayFormat = self.currentItemFormat(value.type.name)
- innerType = value.type.target() # .unqualified()
+ displayFormat = self.currentItemFormat(typename)
+ innerType = value.type.target()
if innerType.name == 'void':
- #DumperBase.warn('VOID POINTER: %s' % displayFormat)
- self.putType(typeName)
+ #self.warn('VOID POINTER: %s' % displayFormat)
+ self.putType(typename)
self.putSymbolValue(pointer)
return
if displayFormat == DisplayFormat.Raw:
# Explicitly requested bald pointer.
- #DumperBase.warn('RAW')
- self.putType(typeName)
+ #self.warn('RAW')
+ self.putType(typename)
self.putValue('0x%x' % pointer)
self.putExpandable()
if self.currentIName in self.expandedINames:
@@ -1384,27 +1511,27 @@ class DumperBase():
limit = self.displayStringLimit
if displayFormat in (DisplayFormat.SeparateLatin1String, DisplayFormat.SeparateUtf8String):
limit = 1000000
- if self.tryPutSimpleFormattedPointer(pointer, typeName,
+ if self.tryPutSimpleFormattedPointer(pointer, typename,
innerType, displayFormat, limit):
self.putExpandable()
return
if DisplayFormat.Array10 <= displayFormat and displayFormat <= DisplayFormat.Array10000:
n = (10, 100, 1000, 10000)[displayFormat - DisplayFormat.Array10]
- self.putType(typeName)
+ self.putType(typename)
self.putItemCount(n)
- self.putArrayData(value.pointer(), n, innerType)
+ self.putArrayData(self.value_as_address(value), n, innerType)
return
if innerType.code == TypeCode.Function:
# A function pointer.
self.putSymbolValue(pointer)
- self.putType(typeName)
+ self.putType(typename)
return
- #DumperBase.warn('AUTODEREF: %s' % self.autoDerefPointers)
- #DumperBase.warn('INAME: %s' % self.currentIName)
- #DumperBase.warn('INNER: %s' % innerType.name)
+ #self.warn('AUTODEREF: %s' % self.autoDerefPointers)
+ #self.warn('INAME: %s' % self.currentIName)
+ #self.warn('INNER: %s' % innerType.name)
if self.autoDerefPointers:
# Generic pointer type with AutomaticFormat, but never dereference char types:
if innerType.name not in (
@@ -1425,9 +1552,9 @@ class DumperBase():
self.putDerefedPointer(value)
return
- #DumperBase.warn('GENERIC PLAIN POINTER: %s' % value.type)
- #DumperBase.warn('ADDR PLAIN POINTER: 0x%x' % value.laddress)
- self.putType(typeName)
+ #self.warn('GENERIC PLAIN POINTER: %s' % value.type)
+ #self.warn('ADDR PLAIN POINTER: 0x%x' % value.laddress)
+ self.putType(typename)
self.putSymbolValue(pointer)
self.putExpandable()
if self.currentIName in self.expandedINames:
@@ -1458,7 +1585,7 @@ class DumperBase():
# - int postedEvents;
# - QDynamicMetaObjectData *metaObject;
# - QBindingStorage bindingStorage;
- extra = self.extractPointer(dd + 9 * ptrSize + 2 * intSize)
+ extra = self.extract_pointer_at_address(dd + 9 * ptrSize + 2 * intSize)
if extra == 0:
return False
@@ -1478,7 +1605,7 @@ class DumperBase():
# - uint isWidget : 1; etc...
# - int postedEvents;
# - QDynamicMetaObjectData *metaObject;
- extra = self.extractPointer(dd + 5 * ptrSize + 2 * intSize)
+ extra = self.extract_pointer_at_address(dd + 5 * ptrSize + 2 * intSize)
if extra == 0:
return False
@@ -1582,7 +1709,7 @@ class DumperBase():
try:
customEventOffset = 8 if self.isMsvcTarget() else 9
- customEventFunc = self.extractPointer(vtablePtr + customEventOffset * self.ptrSize())
+ customEventFunc = self.extract_pointer_at_address(vtablePtr + customEventOffset * self.ptrSize())
except:
self.bump('nostruct-3')
return False
@@ -1594,7 +1721,7 @@ class DumperBase():
customEventFunc = getJumpAddress_x86(self, customEventFunc)
if customEventFunc in (self.qtCustomEventFunc, self.qtCustomEventPltFunc):
return True
- customEventFunc = self.extractPointer(customEventFunc)
+ customEventFunc = self.extract_pointer_at_address(customEventFunc)
if customEventFunc in (self.qtCustomEventFunc, self.qtCustomEventPltFunc):
return True
# If the object is defined in another module there may be another level of indirection
@@ -1603,18 +1730,18 @@ class DumperBase():
return customEventFunc in (self.qtCustomEventFunc, self.qtCustomEventPltFunc)
# def extractQObjectProperty(objectPtr):
-# vtablePtr = self.extractPointer(objectPtr)
-# metaObjectFunc = self.extractPointer(vtablePtr)
+# vtablePtr = self.extract_pointer_at_address(objectPtr)
+# metaObjectFunc = self.extract_pointer_at_address(vtablePtr)
# cmd = '((void*(*)(void*))0x%x)((void*)0x%x)' % (metaObjectFunc, objectPtr)
# try:
-# #DumperBase.warn('MO CMD: %s' % cmd)
+# #self.warn('MO CMD: %s' % cmd)
# res = self.parseAndEvaluate(cmd)
-# #DumperBase.warn('MO RES: %s' % res)
+# #self.warn('MO RES: %s' % res)
# self.bump('successfulMetaObjectCall')
-# return res.pointer()
+# return self.value_as_address(res)
# except:
# self.bump('failedMetaObjectCall')
-# #DumperBase.warn('COULD NOT EXECUTE: %s' % cmd)
+# #self.warn('COULD NOT EXECUTE: %s' % cmd)
# return 0
def extractMetaObjectPtr(self, objectPtr, typeobj):
@@ -1631,29 +1758,29 @@ class DumperBase():
# contents 'vanishes' as the reported size of the string
# gets zeroed out(?).
# Try vtable, metaObject() is the first entry.
- vtablePtr = self.extractPointer(objectPtr)
- metaObjectFunc = self.extractPointer(vtablePtr)
+ vtablePtr = self.extract_pointer_at_address(objectPtr)
+ metaObjectFunc = self.extract_pointer_at_address(vtablePtr)
cmd = '((void*(*)(void*))0x%x)((void*)0x%x)' % (metaObjectFunc, objectPtr)
try:
- #DumperBase.warn('MO CMD: %s' % cmd)
+ #self.warn('MO CMD: %s' % cmd)
res = self.parseAndEvaluate(cmd)
- #DumperBase.warn('MO RES: %s' % res)
+ #self.warn('MO RES: %s' % res)
self.bump('successfulMetaObjectCall')
- return res.pointer()
+ return self.value_as_address(res)
except:
self.bump('failedMetaObjectCall')
- #DumperBase.warn('COULD NOT EXECUTE: %s' % cmd)
+ #self.warn('COULD NOT EXECUTE: %s' % cmd)
return 0
def extractStaticMetaObjectFromTypeHelper(someTypeObj):
if someTypeObj.isSimpleType():
return 0
- typeName = someTypeObj.name
- isQObjectProper = typeName == self.qtNamespace() + 'QObject'
+ typename = someTypeObj.name
+ isQObjectProper = typename == self.qtNamespace() + 'QObject'
# No templates for now.
- if typeName.find('<') >= 0:
+ if typename.find('<') >= 0:
return 0
result = self.findStaticMetaObject(someTypeObj)
@@ -1706,16 +1833,16 @@ class DumperBase():
ptrSize = self.ptrSize()
- typeName = typeobj.name
- result = self.knownStaticMetaObjects.get(typeName, None)
+ typename = typeobj.name
+ result = self.knownStaticMetaObjects.get(typename, None)
if result is not None: # Is 0 or the static metaobject.
self.bump('typecached')
- #DumperBase.warn('CACHED RESULT: %s %s 0x%x' % (self.currentIName, typeName, result))
+ #self.warn('CACHED RESULT: %s %s 0x%x' % (self.currentIName, typename, result))
return result
if not self.couldBeQObjectPointer(objectPtr):
self.bump('cannotBeQObject')
- #DumperBase.warn('DOES NOT LOOK LIKE A QOBJECT: %s' % self.currentIName)
+ #self.warn('DOES NOT LOOK LIKE A QOBJECT: %s' % self.currentIName)
return 0
metaObjectPtr = 0
@@ -1731,26 +1858,17 @@ class DumperBase():
#if metaObjectPtr:
# self.bump('foundMetaObject')
- # self.knownStaticMetaObjects[typeName] = metaObjectPtr
+ # self.8;
return metaObjectPtr
- def split(self, pattern, value):
- if isinstance(value, self.Value):
- return value.split(pattern)
- if self.isInt(value):
- val = self.Value(self)
- val.laddress = value
- return val.split(pattern)
- raise RuntimeError('CANNOT EXTRACT STRUCT FROM %s' % type(value))
-
def extractCString(self, addr):
result = bytearray()
while True:
- d = self.extractByte(addr)
- if d == 0:
+ d = bytes(self.readRawMemory(addr, 1))
+ if d[0] == 0:
break
- result.append(d)
+ result += d
addr += 1
return result
@@ -1775,21 +1893,21 @@ class DumperBase():
data = array + begin * stepSize
return data, size
- def putTypedPointer(self, name, addr, typeName):
+ def putTypedPointer(self, name, addr, typename):
""" Prints a typed pointer, expandable if the type can be resolved,
and without children otherwise """
with SubItem(self, name):
self.putAddress(addr)
self.putValue('@0x%x' % addr)
- typeObj = self.lookupType(typeName)
+ typeObj = self.lookupType(typename)
if typeObj:
self.putType(typeObj)
self.putExpandable()
if self.isExpanded():
with Children(self):
- self.putFields(self.createValue(addr, typeObj))
+ self.putFields(self.createValueFromAddress(addr, typeObj))
else:
- self.putType(typeName)
+ self.putType(typename)
# This is called is when a QObject derived class is expanded
def tryPutQObjectGuts(self, value):
@@ -1803,24 +1921,24 @@ class DumperBase():
stringdataOffset = ptrSize
if self.isWindowsTarget() and self.qtVersion() >= 0x060000:
stringdataOffset += ptrSize # indirect super data member
- stringdata = self.extractPointer(toInteger(metaObjectPtr) + stringdataOffset)
+ stringdata = self.extract_pointer_at_address(int(metaObjectPtr) + stringdataOffset)
- def unpackString(base, size):
+ def unpack_string(base, size):
try:
s = struct.unpack_from('%ds' % size, self.readRawMemory(base, size))[0]
- return s if sys.version_info[0] == 2 else s.decode('utf8')
+ return s.decode('utf8')
except:
return '<not available>'
if revision >= 9: # Qt 6.
pos, size = self.split('II', stringdata + 8 * index)
- return unpackString(stringdata + pos, size)
+ return unpack_string(stringdata + pos, size)
if revision >= 7: # Qt 5.
byteArrayDataSize = 24 if ptrSize == 8 else 16
- literal = stringdata + toInteger(index) * byteArrayDataSize
+ literal = stringdata + int(index) * byteArrayDataSize
base, size, _ = self.qArrayDataHelper(literal)
- return unpackString(base, size)
+ return unpack_string(base, size)
ldata = stringdata + index
return self.extractCString(ldata).decode('utf8')
@@ -1844,11 +1962,11 @@ class DumperBase():
index = name
elif self.qtVersion() >= 0x050000:
revision = 7
- dataPtr = self.extractPointer(metaObjectPtr + 2 * self.ptrSize())
+ dataPtr = self.extract_pointer_at_address(metaObjectPtr + 2 * self.ptrSize())
index = self.extractInt(dataPtr + 4 * handle)
else:
revision = 6
- dataPtr = self.extractPointer(metaObjectPtr + 2 * self.ptrSize())
+ dataPtr = self.extract_pointer_at_address(metaObjectPtr + 2 * self.ptrSize())
index = self.extractInt(dataPtr + 4 * handle)
#self.putValue("index: %s rev: %s" % (index, revision))
name = self.metaString(metaObjectPtr, index, revision)
@@ -1873,14 +1991,14 @@ class DumperBase():
def putQObjectGutsHelper(self, qobject, qobjectPtr, handle, metaObjectPtr, origType):
ptrSize = self.ptrSize()
- def putt(name, value, typeName=' '):
+ def putt(name, value, typename=' '):
with SubItem(self, name):
self.putValue(value)
- self.putType(typeName)
+ self.putType(typename)
def extractSuperDataPtr(someMetaObjectPtr):
#return someMetaObjectPtr['d']['superdata']
- return self.extractPointer(someMetaObjectPtr)
+ return self.extract_pointer_at_address(someMetaObjectPtr)
def extractDataPtr(someMetaObjectPtr):
# dataPtr = metaObjectPtr['d']['data']
@@ -1888,14 +2006,14 @@ class DumperBase():
offset = 3
else:
offset = 2
- return self.extractPointer(someMetaObjectPtr + offset * ptrSize)
+ return self.extract_pointer_at_address(someMetaObjectPtr + offset * ptrSize)
isQMetaObject = origType == 'QMetaObject'
isQObject = origType == 'QObject'
- #DumperBase.warn('OBJECT GUTS: %s 0x%x ' % (self.currentIName, metaObjectPtr))
+ #self.warn('OBJECT GUTS: %s 0x%x ' % (self.currentIName, metaObjectPtr))
dataPtr = extractDataPtr(metaObjectPtr)
- #DumperBase.warn('DATA PTRS: %s 0x%x ' % (self.currentIName, dataPtr))
+ #self.warn('DATA PTRS: %s 0x%x ' % (self.currentIName, dataPtr))
(revision, classname,
classinfo, classinfo2,
methodCount, methods,
@@ -1913,7 +2031,7 @@ class DumperBase():
ns = self.qtNamespace()
extraData = 0
if qobjectPtr:
- dd = self.extractPointer(qobjectPtr + ptrSize)
+ dd = self.extract_pointer_at_address(qobjectPtr + ptrSize)
if self.qtVersion() >= 0x60000:
(dvtablePtr, qptr, parent, children, bindingStorageData, bindingStatus,
flags, postedEvents, dynMetaObjectPtr, # Up to here QObjectData.
@@ -1942,7 +2060,7 @@ class DumperBase():
if not self.isCli:
self.putSortGroup(8)
- dvtablePtr, qptr, parentPtr, children = self.split('ppp{QList<QObject *>}', dd)
+ dvtablePtr, qptr, parentPtr, children = self.split('ppp{@QList<@QObject *>}', dd)
self.putItem(children)
if isQMetaObject:
@@ -2003,8 +2121,9 @@ class DumperBase():
if False:
with SubItem(self, '[connections]'):
if connectionListsPtr:
- typeName = '@QObjectConnectionListVector'
- self.putItem(self.createValue(connectionListsPtr, typeName))
+ typename = '@QObjectConnectionListVector'
+ self.putItem(self.createValueFromAddress(connectionListsPtr,
+typename))
else:
self.putItemCount(0)
@@ -2053,19 +2172,19 @@ class DumperBase():
if qobject and self.qtPropertyFunc:
# LLDB doesn't like calling it on a derived class, possibly
# due to type information living in a different shared object.
- #base = self.createValue(qobjectPtr, '@QObject')
- #DumperBase.warn("CALL FUNC: 0x%x" % self.qtPropertyFunc)
+ #base = self.createValueFromAddress(qobjectPtr, '@QObject')
+ #self.warn("CALL FUNC: 0x%x" % self.qtPropertyFunc)
cmd = '((QVariant(*)(void*,char*))0x%x)((void*)0x%x,"%s")' \
% (self.qtPropertyFunc, qobjectPtr, name)
try:
- #DumperBase.warn('PROP CMD: %s' % cmd)
+ #self.warn('PROP CMD: %s' % cmd)
res = self.parseAndEvaluate(cmd)
- #DumperBase.warn('PROP RES: %s' % res)
+ #self.warn('PROP RES: %s' % res)
except:
self.bump('failedMetaObjectCall')
putt(name, ' ')
continue
- #DumperBase.warn('COULD NOT EXECUTE: %s' % cmd)
+ #self.warn('COULD NOT EXECUTE: %s' % cmd)
#self.putCallItem(name, '@QVariant', base, 'property', '"' + name + '"')
if res is None:
self.bump('failedMetaObjectCall2')
@@ -2077,37 +2196,42 @@ class DumperBase():
# Dynamic properties.
if extraData:
- def list6Generator(addr, innerType):
+ def list6Generator(addr, inner_typeid):
data, size = self.listData(addr)
+ inner_size = self.type_size(inner_typeid)
for i in range(size):
- yield self.createValue(data + i * innerType.size(), innerType)
+ yield self.createValueFromAddress(data, inner_typeid)
+ data += inner_size
- def list5Generator(addr, innerType):
+ def list5Generator(addr, inner_typeid):
data, size = self.listData(addr)
for i in range(size):
- yield self.createValue(data + i * ptrSize, innerType)
+ yield self.createValueFromAddress(data, inner_typeid)
+ data += ptrSize
- def vectorGenerator(addr, innerType):
+ def vectorGenerator(addr, inner_typeid):
data, size = self.vectorData(addr)
+ inner_size = self.type_size(inner_typeid)
for i in range(size):
- yield self.createValue(data + i * innerType.size(), innerType)
+ yield self.createValueFromAddress(data, inner_typeid)
+ data += inner_size
- byteArrayType = self.createType('@QByteArray')
- variantType = self.createType('@QVariant')
+ variant_typeid = self.cheap_typeid_from_name('@QVariant')
if self.qtVersion() >= 0x60000:
- values = vectorGenerator(extraData + 3 * ptrSize, variantType)
+ values = vectorGenerator(extraData + 3 * ptrSize, variant_typeid)
elif self.qtVersion() >= 0x50600:
- values = vectorGenerator(extraData + 2 * ptrSize, variantType)
+ values = vectorGenerator(extraData + 2 * ptrSize, variant_typeid)
elif self.qtVersion() >= 0x50000:
- values = list5Generator(extraData + 2 * ptrSize, variantType)
+ values = list5Generator(extraData + 2 * ptrSize, variant_typeid)
else:
- values = list5Generator(extraData + 2 * ptrSize,
- variantType.pointer())
+ variantptr_typeid = self.cheap_typeid_from_name('@QVariant')
+ values = list5Generator(extraData + 2 * ptrSize, variantptr_typeid)
+ bytearray_typeid = self.cheap_typeid_from_name('@QByteArray')
if self.qtVersion() >= 0x60000:
- names = list6Generator(extraData, byteArrayType)
+ names = list6Generator(extraData, bytearray_typeid)
else:
- names = list5Generator(extraData + ptrSize, byteArrayType)
+ names = list5Generator(extraData + ptrSize, bytearray_typeid)
for (k, v) in zip(names, values):
with SubItem(self, propertyCount + dynamicPropertyCount):
@@ -2169,7 +2293,7 @@ class DumperBase():
if isQObject:
with SubItem(self, '[d]'):
- self.putItem(self.createValue(dd, '@QObjectPrivate'))
+ self.putItem(self.createValueFromAddress(dd, '@QObjectPrivate'))
self.putSortGroup(15)
if isQMetaObject:
@@ -2199,10 +2323,10 @@ class DumperBase():
with SubItem(self, '[connections]'):
ptrSize = self.ptrSize()
self.putNoType()
- privateType = self.createType('@QObjectPrivate')
+ privateType = self.create_typeid_from_name('@QObjectPrivate')
d_ptr = dd.cast(privateType.pointer()).dereference()
connections = d_ptr['connectionLists']
- if self.connections.integer() == 0:
+ if self.value_as_integer(connections) == 0:
self.putItemCount(0)
else:
connections = connections.dereference()
@@ -2215,72 +2339,74 @@ class DumperBase():
innerType = connections.type[0]
# Should check: innerType == ns::QObjectPrivate::ConnectionList
data, size = self.vectorData(connections)
- connectionType = self.createType('@QObjectPrivate::Connection')
+ connection_typeid = self.create_typeid_from_name('@QObjectPrivate::Connection')
+ connection_ptr_typeid = self.create_pointer_typeid(connection_typeid)
for i in range(size):
- first = self.extractPointer(data + i * 2 * ptrSize)
+ first = self.extract_pointer_at_address(data + i * 2 * ptrSize)
while first:
- self.putSubItem('%s' % pp,
- self.createPointerValue(first, connectionType))
- first = self.extractPointer(first + 3 * ptrSize)
+ val = self.Value(self)
+ val.ldata = first
+ val.typeid = connection_typeid
+ self.putSubItem('%s' % pp, val)
+ first = self.extract_pointer_at_address(first + 3 * ptrSize)
# We need to enforce some upper limit.
pp += 1
if pp > 1000:
break
- def currentItemFormat(self, typeName=None):
+ def currentItemFormat(self, typename=None):
displayFormat = self.formats.get(self.currentIName, DisplayFormat.Automatic)
if displayFormat == DisplayFormat.Automatic:
- if typeName is None:
- typeName = self.currentType.value
- needle = None if typeName is None else self.stripForFormat(typeName)
+ if typename is None:
+ typename = self.currentType.value
+ needle = None if typename is None else self.stripForFormat(typename)
displayFormat = self.typeformats.get(needle, DisplayFormat.Automatic)
return displayFormat
def putSubItem(self, component, value): # -> ReportItem
if not isinstance(value, self.Value):
raise RuntimeError('WRONG VALUE TYPE IN putSubItem: %s' % type(value))
- if not isinstance(value.type, self.Type):
- raise RuntimeError('WRONG TYPE TYPE IN putSubItem: %s' % type(value.type))
res = None
with SubItem(self, component):
self.putItem(value)
res = self.currentValue
return res # The 'short' display.
- def putArrayData(self, base, n, innerType, childNumChild=None):
+ def putArrayData(self, base, n, inner_typish, childNumChild=None):
self.checkIntType(base)
self.checkIntType(n)
- addrBase = base
- innerSize = innerType.size()
+ inner_typeid = self.typeid_for_typish(inner_typish)
+ inner_size = self.type_size_cache.get(inner_typeid, None)
self.putNumChild(n)
- #DumperBase.warn('ADDRESS: 0x%x INNERSIZE: %s INNERTYPE: %s' % (addrBase, innerSize, innerType))
- enc = innerType.simpleEncoding()
+ #self.warn('ADDRESS: 0x%x INNERSIZE: %s INNERTYPE: %s' % (base, inner_size, inner_typeid))
+ enc = self.type_encoding_cache.get(inner_typeid, None)
maxNumChild = self.maxArrayCount()
if enc:
- self.put('childtype="%s",' % innerType.name)
- self.put('addrbase="0x%x",' % addrBase)
- self.put('addrstep="0x%x",' % innerSize)
+ self.put('childtype="%s",' % self.type_name(inner_typeid))
+ self.put('addrbase="0x%x",' % base)
+ self.put('addrstep="0x%x",' % inner_size)
self.put('arrayencoding="%s",' % enc)
self.put('endian="%s",' % self.packCode)
if n > maxNumChild:
self.put('childrenelided="%s",' % n)
n = maxNumChild
self.put('arraydata="')
- self.put(self.readMemory(addrBase, n * innerSize))
+ self.put(self.readMemory(base, n * inner_size))
self.put('",')
else:
+ innerType = self.Type(self, inner_typeid)
with Children(self, n, innerType, childNumChild, maxNumChild,
- addrBase=addrBase, addrStep=innerSize):
+ addrBase=base, addrStep=inner_size):
for i in self.childRange():
- self.putSubItem(i, self.createValue(addrBase + i * innerSize, innerType))
+ self.putSubItem(i, self.createValueFromAddress(base + i * inner_size, innerType))
- def putArrayItem(self, name, addr, n, typeName):
+ def putArrayItem(self, name, addr, n, typename):
self.checkIntType(addr)
self.checkIntType(n)
with SubItem(self, name):
self.putEmptyValue()
- self.putType('%s [%d]' % (typeName, n))
- self.putArrayData(addr, n, self.lookupType(typeName))
+ self.putType('%s [%d]' % (typename, n))
+ self.putArrayData(addr, n, self.lookupType(typename))
self.putAddress(addr)
def putPlotDataHelper(self, base, n, innerType, maxNumChild=1000 * 1000):
@@ -2303,13 +2429,15 @@ class DumperBase():
"""
Special handling for char** argv.
"""
+ ptr_size = self.ptrSize()
n = 0
- p = value
- # p is 0 for "optimized out" cases. Or contains rubbish.
+ argv = self.value_as_address(value)
+ # argv is 0 for "optimized out" cases. Or contains rubbish.
try:
- if value.integer():
- while p.dereference().integer() and n <= 100:
- p += 1
+ if argv:
+ p = argv
+ while self.extract_pointer_at_address(p) and n <= 100:
+ p += ptr_size
n += 1
except:
pass
@@ -2325,44 +2453,54 @@ class DumperBase():
self.putSubItem(i, p.dereference())
p += 1
+ def extract_pointer_at_address(self, address):
+ blob = self.value_data_from_address(address, self.ptrSize())
+ return int.from_bytes(blob, byteorder='little')
+
+ def value_extract_integer(self, value, size, signed):
+ if isinstance(value.lvalue, int):
+ return value.lvalue
+ if isinstance(value.ldata, int):
+ return value.ldata
+ #with self.dumper.timer('extractInt'):
+ value.check()
+ blob = self.value_data(value, size)
+ return int.from_bytes(blob, byteorder='little', signed=signed)
+
+ def value_extract_something(self, valuish, size, signed=False):
+ if isinstance(valuish, int):
+ blob = self.value_data_from_address(valuish, size)
+ elif isinstance(valuish, self.Value):
+ blob = self.value_data(valuish, size)
+ else:
+ raise RuntimeError('CANT EXTRACT FROM %s' % type(valuish))
+ res = int.from_bytes(blob, byteorder='little', signed=signed)
+ #self.warn("EXTRACTED %s SIZE %s FROM %s" % (res, size, blob))
+ return res
+
def extractPointer(self, value):
- try:
- if value.type.code == TypeCode.Array:
- return value.address()
- except:
- pass
- code = 'I' if self.ptrSize() == 4 else 'Q'
- return self.extractSomething(value, code, 8 * self.ptrSize())
+ return self.value_extract_something(value, self.ptrSize())
def extractInt64(self, value):
- return self.extractSomething(value, 'q', 64)
+ return self.value_extract_something(value, 8, True)
def extractUInt64(self, value):
- return self.extractSomething(value, 'Q', 64)
+ return self.value_extract_something(value, 8)
def extractInt(self, value):
- return self.extractSomething(value, 'i', 32)
+ return self.value_extract_something(value, 4, True)
def extractUInt(self, value):
- return self.extractSomething(value, 'I', 32)
+ return self.value_extract_something(value, 4)
def extractShort(self, value):
- return self.extractSomething(value, 'h', 16)
+ return self.value_extract_something(value, 2, True)
def extractUShort(self, value):
- return self.extractSomething(value, 'H', 16)
+ return self.value_extract_something(value, 2)
def extractByte(self, value):
- return self.extractSomething(value, 'b', 8)
-
- def extractSomething(self, value, pattern, bitsize):
- if self.isInt(value):
- val = self.Value(self)
- val.laddress = value
- return val.extractSomething(pattern, bitsize)
- if isinstance(value, self.Value):
- return value.extractSomething(pattern, bitsize)
- raise RuntimeError('CANT EXTRACT FROM %s' % type(value))
+ return self.value_extract_something(value, 1)
# Parses a..b and a.(s).b
def parseRange(self, exp):
@@ -2405,9 +2543,9 @@ class DumperBase():
try:
# Allow integral expressions.
- ss = self.parseAndEvaluate(s[1:len(s) - 1]).integer() if s else 1
- aa = self.parseAndEvaluate(a).integer()
- bb = self.parseAndEvaluate(b).integer()
+ ss = self.value_as_integer(self.parseAndEvaluate(s[1:len(s) - 1])) if s else 1
+ aa = self.value_as_integer(self.parseAndEvaluate(a))
+ bb = self.value_as_integer(self.parseAndEvaluate(b))
if aa < bb and ss > 0:
return True, aa, ss, bb + 1, template
except:
@@ -2419,14 +2557,14 @@ class DumperBase():
self.putField('numchild', numchild)
def handleLocals(self, variables):
- #DumperBase.warn('VARIABLES: %s' % variables)
- #with self.timer('locals'):
+ #self.warn('VARIABLES: %s' % variables)
shadowed = {}
for value in variables:
if value.name == 'argv':
if value.type.code == TypeCode.Pointer:
- if value.type.ltarget.code == TypeCode.Pointer:
- if value.type.ltarget.ltarget.name == 'char':
+ target = value.type.target()
+ if target.code == TypeCode.Pointer:
+ if target.target().name == 'char':
self.putSpecialArgv(value)
continue
@@ -2455,7 +2593,7 @@ class DumperBase():
def handleWatch(self, origexp, exp, iname):
exp = str(exp).strip()
escapedExp = self.hexencode(exp)
- #DumperBase.warn('HANDLING WATCH %s -> %s, INAME: "%s"' % (origexp, exp, iname))
+ #self.warn('HANDLING WATCH %s -> %s, INAME: "%s"' % (origexp, exp, iname))
# Grouped items separated by semicolon.
if exp.find(';') >= 0:
@@ -2475,7 +2613,7 @@ class DumperBase():
# Special array index: e.g a[1..199] or a[1.(3).199] for stride 3.
isRange, begin, step, end, template = self.parseRange(exp)
if isRange:
- #DumperBase.warn('RANGE: %s %s %s in %s' % (begin, step, end, template))
+ #self.warn('RANGE: %s %s %s in %s' % (begin, step, end, template))
r = range(begin, end, step)
n = len(r)
with TopLevelItem(self, iname):
@@ -2714,7 +2852,7 @@ class DumperBase():
self.doContinue()
def doInsertInterpreterBreakpoint(self, args, wasPending):
- #DumperBase.warn('DO INSERT INTERPRETER BREAKPOINT, WAS PENDING: %s' % wasPending)
+ #self.warn('DO INSERT INTERPRETER BREAKPOINT, WAS PENDING: %s' % wasPending)
# Will fail if the service is not yet up and running.
response = self.sendInterpreterRequest('setbreakpoint', args)
bp = None if response is None else response.get('breakpoint', None)
@@ -2749,14 +2887,6 @@ class DumperBase():
def extractInterpreterStack(self):
return self.sendInterpreterRequest('backtrace', {'limit': 10})
- def isInt(self, thing):
- if isinstance(thing, int):
- return True
- if sys.version_info[0] == 2:
- if isinstance(thing, long):
- return True
- return False
-
def putItems(self, count, generator, maxNumChild=10000):
self.putItemCount(count)
if self.isExpanded():
@@ -2765,131 +2895,124 @@ class DumperBase():
self.putSubItem(i, val)
def putItem(self, value):
- #with self.timer('putItem'):
- self.putItemX(value)
-
- def putItemX(self, value):
- #DumperBase.warn('PUT ITEM: %s' % value.stringify())
-
- typeobj = value.type # unqualified()
- typeName = typeobj.name
-
- self.addToCache(typeobj) # Fill type cache
+ #self.warn('PUT ITEM: %s' % value.stringify())
+ #self.dump_location()
+ #self.addToCache(typeobj) # Fill type cache
if not value.lIsInScope:
self.putSpecialValue('optimizedout')
- #self.putType(typeobj)
- #self.putSpecialValue('outofscope')
self.putNumChild(0)
return
if not isinstance(value, self.Value):
raise RuntimeError('WRONG TYPE IN putItem: %s' % type(self.Value))
+ typeid = value.typeid
+ typecode = self.type_code(typeid)
+ typename = self.type_name(typeid)
+
# Try on possibly typedefed type first.
- if self.tryPutPrettyItem(typeName, value):
- if typeobj.code == TypeCode.Pointer:
+ if self.tryPutPrettyItem(typename, value):
+ if typecode == TypeCode.Pointer:
self.putOriginalAddress(value.address())
else:
self.putAddress(value.address())
return
- if typeobj.code == TypeCode.Typedef:
- #DumperBase.warn('TYPEDEF VALUE: %s' % value.stringify())
+ if typecode == TypeCode.Typedef:
+ #self.warn('TYPEDEF VALUE: %s' % value.stringify())
self.putItem(value.detypedef())
- self.putBetterType(typeName)
+ self.putBetterType(typename)
return
- if typeobj.code == TypeCode.Pointer:
+ if typecode == TypeCode.Pointer:
self.putFormattedPointer(value)
if value.summary and self.useFancy:
self.putValue(self.hexencode(value.summary), 'utf8:1:0')
return
self.putAddress(value.address())
- if value.lbitsize is not None:
- self.putField('size', value.lbitsize // 8)
- if typeobj.code == TypeCode.Function:
- #DumperBase.warn('FUNCTION VALUE: %s' % value)
- self.putType(typeobj)
- self.putSymbolValue(value.pointer())
+ if typecode == TypeCode.Function:
+ #self.warn('FUNCTION VALUE: %s' % value)
+ self.putType(typeid)
+ self.putSymbolValue(self.value_as_address(value))
self.putNumChild(0)
return
- if typeobj.code == TypeCode.Enum:
- #DumperBase.warn('ENUM VALUE: %s' % value.stringify())
- self.putType(typeobj.name)
+ if typecode == TypeCode.Enum:
+ #self.warn('ENUM VALUE: %s' % value.stringify())
+ self.putType(typename)
self.putValue(value.display())
self.putNumChild(0)
return
- if typeobj.code == TypeCode.Array:
- #DumperBase.warn('ARRAY VALUE: %s' % value)
+ if typecode == TypeCode.Array:
+ #self.warn('ARRAY VALUE: %s' % value)
self.putCStyleArray(value)
return
- if typeobj.code == TypeCode.Bitfield:
- #DumperBase.warn('BITFIELD VALUE: %s %d %s' % (value.name, value.lvalue, typeName))
+ if typecode == TypeCode.Bitfield:
+ #self.warn('BITFIELD VALUE: %s %d %s' % (value.name, value.lvalue, typename))
self.putNumChild(0)
- dd = typeobj.ltarget.tdata.enumDisplay
- self.putValue(str(value.lvalue) if dd is None else dd(
- value.lvalue, value.laddress, '%d'))
- self.putType(typeName)
+ #dd = typeobj.target().enumDisplay
+ #self.putValue(str(value.lvalue) if dd is None else dd(
+ # value.lvalue, value.laddress, '%d'))
+ self.putValue(self.value_as_integer(value))
+ self.putType(typename)
return
- if typeobj.code == TypeCode.Integral:
- #DumperBase.warn('INTEGER: %s %s' % (value.name, value))
- val = value.value()
+ if typecode == TypeCode.Integral:
+ #self.warn('INTEGER: %s %s' % (value.name, value))
self.putNumChild(0)
- self.putValue(val)
- self.putType(typeName)
+ self.putValue(self.value_as_integer(value))
+ self.putType(typename)
return
- if typeobj.code == TypeCode.Float:
- #DumperBase.warn('FLOAT VALUE: %s' % value)
+ if typecode == TypeCode.Float:
+ #self.warn('FLOAT VALUE: %s' % value)
self.putValue(value.value())
self.putNumChild(0)
- self.putType(typeobj.name)
+ self.putType(typename)
return
- if typeobj.code in (TypeCode.Reference, TypeCode.RValueReference):
- #DumperBase.warn('REFERENCE VALUE: %s' % value)
+ if typecode in (TypeCode.Reference, TypeCode.RValueReference):
+ #self.warn('REFERENCE VALUE: %s' % value)
val = value.dereference()
if val.laddress != 0:
self.putItem(val)
else:
self.putSpecialValue('nullreference')
- self.putBetterType(typeName)
+ self.putBetterType(typename)
return
- if typeobj.code == TypeCode.Complex:
- self.putType(typeobj)
+ if typecode == TypeCode.Complex:
+ self.putType(typeid)
self.putValue(value.display())
self.putNumChild(0)
return
- if typeobj.code == TypeCode.FortranString:
+ if typecode == TypeCode.FortranString:
self.putValue(self.hexencode(value.data()), 'latin1')
self.putNumChild(0)
- self.putType(typeobj)
+ self.putType(typeid)
- if typeName.endswith('[]'):
+ if typename.endswith('[]'):
# D arrays, gdc compiled.
n = value['length']
base = value['ptr']
- self.putType(typeName)
+ self.putType(typename)
self.putItemCount(n)
if self.isExpanded():
- self.putArrayData(base.pointer(), n, base.type.target())
+ self.putArrayData(self.value_as_address(base), n, base.type.target())
return
- #DumperBase.warn('SOME VALUE: %s' % value)
- #DumperBase.warn('GENERIC STRUCT: %s' % typeobj)
- #DumperBase.warn('INAME: %s ' % self.currentIName)
- #DumperBase.warn('INAMES: %s ' % self.expandedINames)
- #DumperBase.warn('EXPANDED: %s ' % (self.currentIName in self.expandedINames))
- self.putType(typeName)
+ #self.warn('SOME VALUE: %s' % value)
+ #self.warn('GENERIC STRUCT: %s' % typeid)
+ #self.warn('INAME: %s ' % self.currentIName)
+ #self.warn('INAMES: %s ' % self.expandedINames)
+ #self.warn('EXPANDED: %s ' % (self.currentIName in self.expandedINames))
+ self.putType(typename)
if value.summary is not None and self.useFancy:
self.putValue(self.hexencode(value.summary), 'utf8:1:0')
@@ -2898,7 +3021,7 @@ class DumperBase():
self.putExpandable()
self.putEmptyValue()
- #DumperBase.warn('STRUCT GUTS: %s ADDRESS: 0x%x ' % (value.name, value.address()))
+ #self.warn('STRUCT GUTS: %s ADDRESS: 0x%x ' % (value.name, value.address()))
if self.showQObjectNames:
#with self.timer(self.currentIName):
self.putQObjectNameValue(value)
@@ -2911,8 +3034,8 @@ class DumperBase():
self.tryPutQObjectGuts(value)
def symbolAddress(self, symbolName):
- res = self.parseAndEvaluate('(size_t)&' + symbolName)
- return None if res is None else res.pointer()
+ res = self.parseAndEvaluate('(void *)&' + symbolName)
+ return None if res is None else self.value_as_address(res)
def qtHookDataSymbolName(self):
return 'qtHookData'
@@ -2922,7 +3045,7 @@ class DumperBase():
if addr:
# Only available with Qt 5.3+
(hookVersion, x, x, x, x, x, tiVersion) = self.split('ppppppp', addr)
- #DumperBase.warn('HOOK: %s TI: %s' % (hookVersion, tiVersion))
+ #self.warn('HOOK: %s TI: %s' % (hookVersion, tiVersion))
if hookVersion >= 3:
self.qtTypeInfoVersion = lambda: tiVersion
return tiVersion
@@ -2954,16 +3077,15 @@ class DumperBase():
#self._stack = inspect.stack()
self.dumper = dumper
self.name = None
- self._type = None
+ self.typeid = None
+ self.code = None
+ self.size = None
self.ldata = None # Target address in case of references and pointers.
self.laddress = None # Own address.
self.lvalue = None
self.lIsInScope = True
self.ldisplay = None
self.summary = None # Always hexencoded UTF-8.
- self.lbitpos = None
- self.lbitsize = None
- self.targetValue = None # For references.
self.isBaseClass = None
self.nativeValue = None
self.autoDerefCount = 0
@@ -2972,49 +3094,47 @@ class DumperBase():
val = self.dumper.Value(self.dumper)
val.dumper = self.dumper
val.name = self.name
- val._type = self._type
+ val.typeid = self.typeid
+ val.code = self.code = None
+ val.size = self.size
val.ldata = self.ldata
val.laddress = self.laddress
+ val.lvalue = self.lvalue
val.lIsInScope = self.lIsInScope
val.ldisplay = self.ldisplay
val.summary = self.summary
- val.lbitpos = self.lbitpos
- val.lbitsize = self.lbitsize
- val.targetValue = self.targetValue
val.nativeValue = self.nativeValue
return val
@property
def type(self):
- if self._type is None and self.nativeValue is not None:
- self._type = self.dumper.nativeValueType(self.nativeValue)
- return self._type
+ return self.dumper.Type(self.dumper, self.typeid)
def check(self):
- if self.laddress is not None and not self.dumper.isInt(self.laddress):
- raise RuntimeError('INCONSISTENT ADDRESS: %s' % type(self.laddress))
- if self.type is not None and not isinstance(self.type, self.dumper.Type):
- raise RuntimeError('INCONSISTENT TYPE: %s' % type(self.type))
+ #if self.typeid is not None and not isinstance(self.typeid, int):
+ # raise RuntimeError('INCONSISTENT TYPE: %s' % type(self.typeid))
+ #if self.laddress is not None and not isinstance(self.laddress, int):
+ # raise RuntimeError('INCONSISTENT ADDRESS: %s' % type(self.laddress))
+ pass
def __str__(self):
#raise RuntimeError('Not implemented')
return self.stringify()
def __int__(self):
- return self.integer()
+ return self.dumper.value_as_integer(self)
def stringify(self):
addr = 'None' if self.laddress is None else ('0x%x' % self.laddress)
- return "Value(name='%s',type=%s,bsize=%s,bpos=%s,data=%s,address=%s)" \
- % (self.name, self.type.name, self.lbitsize, self.lbitpos,
- self.dumper.hexencode(self.ldata), addr)
+ if isinstance(self.ldata, int):
+ data = str(self.ldata)
+ else:
+ data = self.dumper.hexencode(self.ldata)
+ return "Value(name='%s',typeid=%s, type=%s,data=%s,address=%s)" \
+ % (self.name, self.typeid, self.type.name, data, addr)
def displayEnum(self, form='%d', bitsize=None):
- intval = self.integer(bitsize)
- dd = self.type.tdata.enumDisplay
- if dd is None:
- return str(intval)
- return dd(intval, self.laddress, form)
+ return self.dumper.value_display_enum(self, form, bitsize)
def display(self):
if self.ldisplay is not None:
@@ -3023,451 +3143,70 @@ class DumperBase():
if simple is not None:
return str(simple)
#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')
if self.laddress is not None:
return 'value of type %s at address 0x%x' % (self.type.name, self.laddress)
return '<unknown data>'
def pointer(self):
- if self.type.code == TypeCode.Typedef:
- return self.detypedef().pointer()
- return self.extractInteger(self.dumper.ptrSize() * 8, True)
-
- def integer(self, bitsize=None):
- if self.type.code == TypeCode.Typedef:
- return self.detypedef().integer()
- elif isinstance(self.lvalue, int):
- return self.lvalue
- # Could be something like 'short unsigned int'
- unsigned = self.type.name == 'unsigned' \
- or self.type.name.startswith('unsigned ') \
- or self.type.name.find(' unsigned ') != -1
- if bitsize is None:
- bitsize = self.type.lbitsize
- return self.extractInteger(bitsize, unsigned)
+ return self.dumper.value_as_address(self)
+
+ def as_address(self):
+ return self.dumper.value_as_address(self)
+
+ def integer(self):
+ return self.dumper.value_as_integer(self)
def floatingPoint(self):
- if self.nativeValue is not None and not self.dumper.isCdb:
- return str(self.nativeValue)
- if self.type.code == TypeCode.Typedef:
- return self.detypedef().floatingPoint()
- if self.type.size() == 8:
- return self.extractSomething('d', 64)
- if self.type.size() == 4:
- return self.extractSomething('f', 32)
- # Fall back in case we don't have a nativeValue at hand.
- # FIXME: This assumes Intel's 80bit extended floats. Which might
- # be wrong.
- l, h = self.split('QQ')
- if True: # 80 bit floats
- sign = (h >> 15) & 1
- exp = (h & 0x7fff)
- fraction = l
- bit63 = (l >> 63) & 1
- #DumperBase.warn("SIGN: %s EXP: %s H: 0x%x L: 0x%x" % (sign, exp, h, l))
- if exp == 0:
- if bit63 == 0:
- if l == 0:
- res = '-0' if sign else '0'
- else:
- res = (-1)**sign * l * 2**(-16382) # subnormal
- else:
- res = 'pseudodenormal'
- elif exp == 0x7fff:
- res = 'special'
- else:
- res = (-1)**sign * l * 2**(exp - 16383 - 63)
- else: # 128 bits
- sign = h >> 63
- exp = (h >> 48) & 0x7fff
- fraction = h & (2**48 - 1)
- #DumperBase.warn("SIGN: %s EXP: %s FRAC: %s H: 0x%x L: 0x%x" % (sign, exp, fraction, h, l))
- if exp == 0:
- if fraction == 0:
- res = -0.0 if sign else 0.0
- else:
- res = (-1)**sign * fraction / 2**48 * 2**(-62) # subnormal
- elif exp == 0x7fff:
- res = ('-inf' if sign else 'inf') if fraction == 0 else 'nan'
- else:
- res = (-1)**sign * (1 + fraction / 2**48) * 2**(exp - 63)
- return res
+ return self.dumper.value_as_floating_point(self)
def value(self):
- if self.type is not None:
- if self.type.code == TypeCode.Enum:
- return self.displayEnum()
- if self.type.code == TypeCode.Typedef:
- return self.detypedef().value()
- if self.type.code == TypeCode.Integral:
- return self.integer()
- if self.type.code == TypeCode.Bitfield:
- return self.integer()
- if self.type.code == TypeCode.Float:
- return self.floatingPoint()
- if self.type.code == TypeCode.Pointer:
- return self.pointer()
- return None
+ return self.dumper.value_display(self)
def extractPointer(self):
- return self.split('p')[0]
+ return self.dumper.value_extract_something(self, self.dumper.ptrSize())
def hasMember(self, name):
- return self.findMemberByName(name) is not None
+ return self.dumper.value_member_by_name(self, name) is not None
- def findMemberByName(self, name):
- self.check()
- if self.type.code == TypeCode.Typedef:
- return self.findMemberByName(self.detypedef())
- if self.type.code in (
- TypeCode.Pointer,
- TypeCode.Reference,
- TypeCode.RValueReference):
- res = self.dereference().findMemberByName(name)
- if res is not None:
- return res
- if self.type.code == TypeCode.Struct:
- #DumperBase.warn('SEARCHING FOR MEMBER: %s IN %s' % (name, self.type.name))
- members = self.members(True)
- #DumperBase.warn('MEMBERS: %s' % members)
- for member in members:
- #DumperBase.warn('CHECKING FIELD %s' % member.name)
- if member.type.code == TypeCode.Typedef:
- member = member.detypedef()
- if member.name == name:
- return member
- for member in members:
- if member.type.code == TypeCode.Typedef:
- member = member.detypedef()
- if member.name == name: # Could be base class.
- return member
- if member.type.code == TypeCode.Struct:
- res = member.findMemberByName(name)
- if res is not None:
- return res
- return None
+ def __getitem__(self, indexish):
+ return self.dumper.value_member_by_indexish(self, indexish)
- def __getitem__(self, index):
- #DumperBase.warn('GET ITEM %s %s' % (self, index))
- self.check()
- if self.type.code == TypeCode.Typedef:
- #DumperBase.warn('GET ITEM STRIP TYPEDEFS TO %s' % self.type.ltarget)
- return self.cast(self.type.ltarget).__getitem__(index)
- if isinstance(index, str):
- if self.type.code == TypeCode.Pointer:
- #DumperBase.warn('GET ITEM %s DEREFERENCE TO %s' % (self, self.dereference()))
- return self.dereference().__getitem__(index)
- res = self.findMemberByName(index)
- if res is None:
- raise RuntimeError('No member named %s in type %s'
- % (index, self.type.name))
- return res
- elif isinstance(index, self.dumper.Field):
- field = index
- elif self.dumper.isInt(index):
- if self.type.code == TypeCode.Array:
- addr = self.laddress + int(index) * self.type.ltarget.size()
- return self.dumper.createValue(addr, self.type.ltarget)
- if self.type.code == TypeCode.Pointer:
- addr = self.pointer() + int(index) * self.type.ltarget.size()
- return self.dumper.createValue(addr, self.type.ltarget)
- return self.members(False)[index]
- else:
- raise RuntimeError('BAD INDEX TYPE %s' % type(index))
- field.check()
-
- #DumperBase.warn('EXTRACT FIELD: %s, BASE 0x%x' % (field, self.address()))
- if self.type.code == TypeCode.Pointer:
- #DumperBase.warn('IS TYPEDEFED POINTER!')
- res = self.dereference()
- #DumperBase.warn('WAS POINTER: %s' % res)
-
- return field.extract(self)
-
- def extractField(self, field):
- if not isinstance(field, self.dumper.Field):
- raise RuntimeError('BAD INDEX TYPE %s' % type(field))
-
- if field.extractor is not None:
- val = field.extractor(self)
- if val is not None:
- #DumperBase.warn('EXTRACTOR SUCCEEDED: %s ' % val)
- return val
-
- if self.type.code == TypeCode.Typedef:
- return self.cast(self.type.ltarget).extractField(field)
- if self.type.code in (TypeCode.Reference, TypeCode.RValueReference):
- return self.dereference().extractField(field)
- #DumperBase.warn('FIELD: %s ' % (field,))
- val = self.dumper.Value(self.dumper)
- val.name = field.name
- val.isBaseClass = field.isBase
- val._type = field.fieldType()
-
- if field.isArtificial:
- if self.laddress is not None:
- val.laddress = self.laddress
- if self.ldata is not None:
- val.ldata = self.ldata
- return val
-
- fieldBitsize = field.bitsize
- fieldSize = (fieldBitsize + 7) // 8
- fieldBitpos = field.bitpos
- fieldOffset = fieldBitpos // 8
- fieldType = field.fieldType()
-
- if fieldType.code == TypeCode.Bitfield:
- fieldBitpos -= fieldOffset * 8
- ldata = self.data()
- data = 0
- for i in range(fieldSize):
- data = data << 8
- if self.dumper.isBigEndian:
- lbyte = ldata[i]
- else:
- lbyte = ldata[fieldOffset + fieldSize - 1 - i]
- if isinstance(lbyte, (str, bytes)):
- data += ord(lbyte)
- else:
- data += lbyte
- data = data >> fieldBitpos
- data = data & ((1 << fieldBitsize) - 1)
- val.lvalue = data
- val.laddress = None
- return val
-
- if self.laddress is not None:
- val.laddress = self.laddress + fieldOffset
- elif self.ldata is not None:
- val.ldata = self.ldata[fieldOffset:fieldOffset + fieldSize]
- else:
- self.dumper.check(False)
-
- if fieldType.code in (TypeCode.Reference, TypeCode.RValueReference):
- if val.laddress is not None:
- val = self.dumper.createReferenceValue(val.laddress, fieldType.ltarget)
- val.name = field.name
-
- #DumperBase.warn('GOT VAL %s FOR FIELD %s' % (val, field))
- val.lbitsize = fieldBitsize
- val.check()
- return val
-
- # This is the generic version for synthetic values.
- # The native backends replace it in their fromNativeValue()
- # implementations.
- def members(self, includeBases):
- #DumperBase.warn("LISTING MEMBERS OF %s" % self)
- if self.type.code == TypeCode.Typedef:
- return self.detypedef().members(includeBases)
-
- tdata = self.type.tdata
- #if isinstance(tdata.lfields, list):
- # return tdata.lfields
-
- fields = []
- if tdata.lfields is not None:
- if isinstance(tdata.lfields, list):
- fields = tdata.lfields
- else:
- fields = list(tdata.lfields(self))
-
- #DumperBase.warn("FIELDS: %s" % fields)
- res = []
- for field in fields:
- if isinstance(field, self.dumper.Value):
- #DumperBase.warn("USING VALUE DIRECTLY %s" % field.name)
- res.append(field)
- continue
- if field.isBase and not includeBases:
- #DumperBase.warn("DROPPING BASE %s" % field.name)
- continue
- res.append(self.extractField(field))
- #DumperBase.warn("GOT MEMBERS: %s" % res)
- return res
+ def members(self, include_bases):
+ return self.dumper.value_members(self, include_bases)
def __add__(self, other):
- self.check()
- if self.dumper.isInt(other):
- stripped = self.type.stripTypedefs()
- if stripped.code == TypeCode.Pointer:
- address = self.pointer() + stripped.dereference().size() * other
- val = self.dumper.Value(self.dumper)
- val.laddress = None
- val.ldata = bytes(struct.pack(self.dumper.packCode + 'Q', address))
- val._type = self._type
- return val
- raise RuntimeError('BAD DATA TO ADD TO: %s %s' % (self.type, other))
+ return self.dumper.value_plus_something(self, other)
def __sub__(self, other):
- self.check()
- if self.type.name == other.type.name:
- stripped = self.type.stripTypedefs()
- if stripped.code == TypeCode.Pointer:
- return (self.pointer() - other.pointer()) // stripped.dereference().size()
- raise RuntimeError('BAD DATA TO SUB TO: %s %s' % (self.type, other))
+ return self.dumper.value_minus_something(self, other)
def dereference(self):
- self.check()
- if self.type.code == TypeCode.Typedef:
- return self.detypedef().dereference()
- val = self.dumper.Value(self.dumper)
- if self.type.code in (TypeCode.Reference, TypeCode.RValueReference):
- val.summary = self.summary
- if self.nativeValue is None:
- val.laddress = self.pointer()
- if val.laddress is None and self.laddress is not None:
- val.laddress = self.laddress
- val._type = self.type.dereference()
- if self.dumper.useDynamicType:
- val._type = self.dumper.nativeDynamicType(val.laddress, val.type)
- else:
- val = self.dumper.nativeValueDereferenceReference(self)
- elif self.type.code == TypeCode.Pointer:
- try:
- val = self.dumper.nativeValueDereferencePointer(self)
- except:
- val.laddress = self.pointer()
- val._type = self.type.dereference()
- if self.dumper.useDynamicType:
- val._type = self.dumper.nativeDynamicType(val.laddress, val.type)
- else:
- raise RuntimeError("WRONG: %s" % self.type.code)
- #DumperBase.warn("DEREFERENCING FROM: %s" % self)
- #DumperBase.warn("DEREFERENCING TO: %s" % val)
- #dynTypeName = val.type.dynamicTypeName(val.laddress)
- #if dynTypeName is not None:
- # val._type = self.dumper.createType(dynTypeName)
- return val
+ return self.dumper.value_dereference(self)
def detypedef(self):
- self.check()
- if self.type.code != TypeCode.Typedef:
- raise RuntimeError("WRONG")
- val = self.copy()
- val._type = self.type.ltarget
- #DumperBase.warn("DETYPEDEF FROM: %s" % self)
- #DumperBase.warn("DETYPEDEF TO: %s" % val)
- return val
-
- def extend(self, size):
- if self.type.size() < size:
- val = self.dumper.Value(self.dumper)
- val.laddress = None
- val.ldata = self.zeroExtend(self.ldata)
- return val
- if self.type.size() == size:
- return self
- raise RuntimeError('NOT IMPLEMENTED')
-
- def zeroExtend(self, data, size):
- ext = '\0' * (size - len(data))
- 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 self.dumper.value_detypedef(self)
def cast(self, typish):
- self.check()
- val = self.dumper.Value(self.dumper)
- val.laddress = self.laddress
- val.lbitsize = self.lbitsize
- val.ldata = self.ldata
- val._type = self.dumper.createType(typish)
- return val
+ return self.dumper.value_cast(self, typish)
def address(self):
self.check()
return self.laddress
- def data(self, size=None):
- self.check()
- if self.ldata is not None:
- if len(self.ldata) > 0:
- if size is None:
- return self.ldata
- if size == len(self.ldata):
- return self.ldata
- if size < len(self.ldata):
- return self.ldata[:size]
- #raise RuntimeError('ZERO-EXTENDING DATA TO %s BYTES: %s' % (size, self))
- return self.zeroExtend(self.ldata, size)
- if self.laddress is not None:
- if size is None:
- size = self.type.size()
- res = self.dumper.readRawMemory(self.laddress, size)
- if len(res) > 0:
- return res
- raise RuntimeError('CANNOT CONVERT ADDRESS TO BYTES: %s' % self)
- raise RuntimeError('CANNOT CONVERT TO BYTES: %s' % self)
-
- def extractInteger(self, bitsize, unsigned):
- #with self.dumper.timer('extractInt'):
- self.check()
- if bitsize > 32:
- size = 8
- code = 'Q' if unsigned else 'q'
- elif bitsize > 16:
- size = 4
- code = 'I' if unsigned else 'i'
- elif bitsize > 8:
- size = 2
- code = 'H' if unsigned else 'h'
- else:
- size = 1
- code = 'B' if unsigned else 'b'
- rawBytes = self.data(size)
- res = struct.unpack_from(self.dumper.packCode + code, rawBytes, 0)[0]
- #DumperBase.warn('Extract: Code: %s Bytes: %s Bitsize: %s Size: %s'
- # % (self.dumper.packCode + code, self.dumper.hexencode(rawBytes), bitsize, size))
- return res
-
- def extractSomething(self, code, bitsize):
- #with self.dumper.timer('extractSomething'):
- self.check()
- size = (bitsize + 7) >> 3
- rawBytes = self.data(size)
- res = struct.unpack_from(self.dumper.packCode + code, rawBytes, 0)[0]
- return res
+ def data(self):
+ return self.dumper.value_data(self, self.dumper.type_size(self.typeid))
def to(self, pattern):
return self.split(pattern)[0]
def split(self, pattern):
- #with self.dumper.timer('split'):
- #DumperBase.warn('EXTRACT STRUCT FROM: %s' % self.type)
- (pp, size, fields) = self.dumper.describeStruct(pattern)
- #DumperBase.warn('SIZE: %s ' % size)
- result = struct.unpack_from(self.dumper.packCode + pp, self.data(size))
-
- def structFixer(field, thing):
- #DumperBase.warn('STRUCT MEMBER: %s' % type(thing))
- if field.isStruct:
- #if field.type != field.fieldType():
- # raise RuntimeError('DO NOT SIMPLIFY')
- #DumperBase.warn('FIELD POS: %s' % field.type.stringify())
- #DumperBase.warn('FIELD TYE: %s' % field.fieldType().stringify())
- res = self.dumper.createValue(thing, field.fieldType())
- #DumperBase.warn('RES TYPE: %s' % res.type)
- if self.laddress is not None:
- res.laddress = self.laddress + field.offset()
- return res
- return thing
- if len(fields) != len(result):
- raise RuntimeError('STRUCT ERROR: %s %s' % (fields, result))
- return tuple(map(structFixer, fields, result))
+ return self.dumper.value_split(self, pattern)
def checkPointer(self, p, align=1):
- ptr = p if self.isInt(p) else p.pointer()
+ ptr = p if isinstance(p, int) else p.pointer()
self.readRawMemory(ptr, 1)
- def type(self, typeId):
- return self.typeData.get(typeId)
-
def splitArrayType(self, type_name):
# "foo[2][3][4]" -> ("foo", "[3][4]", 2)
pos1 = len(type_name)
@@ -3481,249 +3220,171 @@ class DumperBase():
item_count = type_name[pos1 + 1:pos2]
return (type_name[0:pos1].strip(), type_name[pos2 + 1:].strip(), int(item_count))
- def registerTypeAlias(self, existingTypeId, aliasId):
- #DumperBase.warn('REGISTER ALIAS %s FOR %s' % (aliasId, existingTypeId))
- self.typeData[aliasId] = self.typeData[existingTypeId]
-
- class TypeData():
- def __init__(self, dumper, type_id):
- self.dumper = dumper
- self.lfields = None # None or Value -> list of member Values
- self.lalignment = None # Function returning alignment of this struct
- self.lbitsize = None
- self.ltarget = None # Inner type for arrays
- self.templateArguments = None
- self.code = None
- self.name = type_id
- self.typeId = type_id
- self.enumDisplay = None
- self.moduleName = None
- #DumperBase.warn('REGISTER TYPE: %s' % type_id)
- dumper.typeData[type_id] = self
-
- def copy(self):
- tdata = self.dumper.TypeData(self.dumper, self.typeId)
- tdata.dumper = self.dumper
- tdata.lfields = self.lfields
- tdata.lalignment = self.lalignment
- tdata.lbitsize = self.lbitsize
- tdata.ltarget = self.ltarget
- tdata.templateArguments = self.templateArguments
- tdata.code = self.code
- tdata.name = self.name
- tdata.typeId = self.typeId
- tdata.enumDisplay = self.enumDisplay
- tdata.moduleName = self.moduleName
- return tdata
-
- @property
- def bitsize(self):
- if callable(self.lbitsize):
- self.lbitsize = self.lbitsize()
- return self.lbitsize
+ def registerTypeAlias(self, existing_type_id, alias_id):
+ #self.warn('REGISTER ALIAS %s FOR %s' % (aliasId, existingTypeId))
+ self.type_alias[alias_id] = existing_type_id
+
+ def init_type_cache(self):
+ self.type_name_cache = {}
+ self.type_fields_cache = {}
+ self.type_alignment_cache = {}
+ self.type_bitsize_cache = {}
+ self.type_size_cache = {}
+ self.type_target_cache = {}
+ self.type_template_arguments_cache = {}
+ self.type_code_cache = {}
+ self.type_enum_display_cache = {}
+ self.type_module_name_cache = {}
+ self.type_nativetype_cache = {}
+ self.type_modulename_cache = {}
+ self.type_encoding_cache = {}
+ self.typeid_cache = {} # internal typename -> id
+ self.typeid_current = 100
+ self.typeid_from_typekey = {} # typename -> id
+
+ def dump_type_cache(self):
+ self.warn('NAME: %s' % self.type_name_cache)
+ self.warn('CODE: %s' % self.type_code_cache)
+ #self.warn('FIELDS: %s' % self.type_fields_cache)
+ self.warn('SIZE: %s' % self.type_size_cache)
+ self.warn('TARGS: %s' % self.type_template_arguments_cache)
+ self.warn('BITSIZE: %s' % self.type_bitsize_cache)
+ self.warn('TARGET: %s' % self.type_target_cache)
+ #self.warn('NATIVETYPE: %s' % self.type_nativetype_cache)
+
+ def dump_typeid(self, typeid):
+ self.warn(' NAME: %s' % self.type_name_cache.get(typeid, None))
+ self.warn(' CODE: %s' % self.type_code_cache.get(typeid, None))
+ #self.warn(' FIELDS: %s' % self.type_fields_cache.get(typeid, None))
+ self.warn(' SIZE: %s' % self.type_size_cache.get(typeid, None))
+ self.warn(' TARGS: %s' % self.type_template_arguments_cache.get(typeid, None))
+ self.warn(' BITSIZE: %s' % self.type_bitsize_cache.get(typeid, None))
+ self.warn(' TARGET: %s' % self.type_target_cache.get(typeid, None))
+ #self.warn(' NATIVETYPE: %s' % self.type_nativetype_cache.get(typeid, None))
+
+ def typeid_for_typish(self, typish):
+ if isinstance(typish, int):
+ return typish
+ if isinstance(typish, str):
+ return self.typeid_for_string(typish)
+ if isinstance(typish, self.Type):
+ return typish.typeid
+ self.warn('NO TYPE FOR TYPISH: %s' % str(typish))
+ return 0
+
+ def sanitize_type_name(self, typeid_str):
+ if not ' ' in typeid_str:
+ # FIXME: This uses self.qtNamespace() too early.
+ #typeid_arr.append(self.qtNamespace())
+ return typeid_str.replace('@', '')
+ typeid_arr = []
+ last_char_was_space = False
+ for c in typeid_str:
+ if c == '@' in typeid_str:
+ # FIXME: This uses self.qtNamespace() too early.
+ #typeid_arr.append(self.qtNamespace())
+ pass
+ elif c == ' ':
+ last_char_was_space = True
+ elif c in '&*<>,':
+ last_char_was_space = False
+ typeid_arr.append(c)
+ else:
+ if last_char_was_space:
+ typeid_arr.append(' ')
+ last_char_was_space = False
+ typeid_arr.append(c)
+ #self.warn("SANITIZE: '%s' TO '%s'" % (typeid_str, ''.join(typeid_arr)))
+ return ''.join(typeid_arr)
+
+ def typeid_for_string(self, typeid_str, type_name=None):
+ #typeid = self.typeid_cache.get(typeid_str, None)
+ #if typeid is not None:
+ # return typeid
+ sane_typeid_str = self.sanitize_type_name(typeid_str)
+ typeid = self.typeid_cache.get(sane_typeid_str, None)
+ if typeid is not None:
+ return typeid
+
+ self.typeid_current += 1
+ if type_name is None:
+ type_name = sane_typeid_str
+ typeid = self.typeid_current
+ self.typeid_cache[typeid_str] = typeid
+ self.typeid_cache[sane_typeid_str] = typeid
+ self.type_name_cache[typeid] = type_name
+ #if typeid == 103:
+ #self.warn("CREATED TYPE: %d %s" % (typeid, sane_typeid_str))
+ #if typeid == 135: self.dump_location()
+ return typeid
class Type():
- def __init__(self, dumper, typeId):
- self.typeId = typeId.replace('@', dumper.qtNamespace())
+ __slots__ = ['dumper', 'typeid']
+ def __init__(self, dumper, typeid):
self.dumper = dumper
- self.initialized = False
+ self.typeid = typeid
def __str__(self):
- #return self.typeId
- return self.stringify()
-
- @property
- def tdata(self):
- if not self.initialized:
- self.initialized = True
- self.data = self.dumper.typeData.get(self.typeId, None)
- if self.data is None:
- #DumperBase.warn('USING : %s' % self.typeId)
- self.dumper.lookupType(self.typeId)
- self.data = self.dumper.typeData.get(self.typeId)
- return self.data
-
- def setTdata(self, tdata):
- self.initialized = True
- self.data = tdata
+ return self.dumper.type_stringify(self.typeid)
@property
def name(self):
- return self.typeId if self.tdata is None else self.tdata.name
+ return self.dumper.type_name(self.typeid)
@property
def code(self):
- return self.tdata.code
+ return self.dumper.type_code(self.typeid)
- @property
- def lbitsize(self):
- return self.tdata.bitsize
+ def bitsize(self):
+ return self.dumper.type_bitsize(self.typeid)
- @property
- def lbitpos(self):
- return self.tdata.lbitpos
+ def size(self):
+ return self.dumper.type_size(self.typeid)
- @property
- def ltarget(self):
- if isinstance(self.tdata.ltarget, str):
- self.tdata.ltarget = self.dumper.createType(self.tdata.ltarget)
- return self.tdata.ltarget
+ def target(self):
+ return self.dumper.Type(self.dumper, self.dumper.type_target(self.typeid))
@property
def targetName(self):
- if self.tdata.ltarget is None:
+ target = self.target()
+ if target is None:
return ''
- return self.tdata.ltarget if isinstance(self.tdata.ltarget, str) else self.tdata.ltarget.name
+ return target if isinstance(target, str) else target.name
@property
def moduleName(self):
- if callable(self.tdata.moduleName):
- self.tdata.moduleName = self.tdata.moduleName()
- return self.tdata.moduleName
-
- def stringify(self):
- return 'Type(name="%s",bsize=%s,code=%s)' \
- % (self.tdata.name, self.lbitsize, self.tdata.code)
+ return self.dumper.type_modulename_cache.get(self.typeid, None)
def __getitem__(self, index):
- if self.dumper.isInt(index):
- return self.templateArgument(index)
+ if isinstance(index, int):
+ return self.dumper.type_template_argument(self.typeid, index)
raise RuntimeError('CANNOT INDEX TYPE')
- def dynamicTypeName(self, address):
- if self.tdata.code != TypeCode.Struct:
- return None
- try:
- vtbl = self.dumper.extractPointer(address)
- except:
- return None
- #DumperBase.warn('VTBL: 0x%x' % vtbl)
- if not self.dumper.couldBePointer(vtbl):
- return None
- return self.dumper.nativeDynamicTypeName(address, self)
-
- def dynamicType(self, address):
- # FIXME: That buys some performance at the cost of a fail
- # of Gdb13393 dumper test.
- #return self
- #with self.dumper.timer('dynamicType %s 0x%s' % (self.name, address)):
- dynTypeName = self.dynamicTypeName(address)
- if dynTypeName is not None:
- return self.dumper.createType(dynTypeName)
- return self
-
def check(self):
- if self.tdata.name is None:
- raise RuntimeError('TYPE WITHOUT NAME: %s' % self.typeId)
+ #if self.tdata.name is None:
+ # raise RuntimeError('TYPE WITHOUT NAME: %s' % self.typeid)
+ pass
def dereference(self):
- if self.code == TypeCode.Typedef:
- return self.ltarget.dereference()
- self.check()
- return self.ltarget
-
- def unqualified(self):
- return self
+ return self.dumper.Type(self.dumper, self.dumper.type_dereference(self.typeid))
def templateArguments(self):
- if self.tdata is None:
- return self.dumper.listTemplateParameters(self.typeId)
- return self.tdata.templateArguments()
-
- def templateArgument(self, position):
- #DumperBase.warn('TDATA: %s' % self.tdata)
- #DumperBase.warn('ID: %s' % self.typeId)
- if self.tdata is None or self.tdata.templateArguments is None:
- # Native lookups didn't help. Happens for 'wrong' placement of 'const'
- # etc. with LLDB. But not all is lost:
- ta = self.dumper.listTemplateParameters(self.typeId)
- #DumperBase.warn('MANUAL: %s' % ta)
- res = ta[position]
- #DumperBase.warn('RES: %s' % res.typeId)
- return res
- #DumperBase.warn('TA: %s %s' % (position, self.typeId))
- #DumperBase.warn('ARGS: %s' % self.tdata.templateArguments())
- return self.tdata.templateArguments()[position]
-
- def simpleEncoding(self):
- res = {
- 'bool': 'int:1',
- 'char': 'int:1',
- 'int8_t': 'int:1',
- 'qint8': 'int:1',
- 'signed char': 'int:1',
- 'char8_t': 'uint:1',
- 'unsigned char': 'uint:1',
- 'uint8_t': 'uint:1',
- 'quint8': 'uint:1',
- 'short': 'int:2',
- 'int16_t': 'int:2',
- 'qint16': 'int:2',
- 'unsigned short': 'uint:2',
- 'char16_t': 'uint:2',
- 'uint16_t': 'uint:2',
- 'quint16': 'uint:2',
- 'int': 'int:4',
- 'int32_t': 'int:4',
- 'qint32': 'int:4',
- 'unsigned int': 'uint:4',
- 'char32_t': 'uint:4',
- 'uint32_t': 'uint:4',
- 'quint32': 'uint:4',
- 'long long': 'int:8',
- 'int64_t': 'int:8',
- 'qint64': 'int:8',
- 'unsigned long long': 'uint:8',
- 'uint64_t': 'uint:8',
- 'quint64': 'uint:8',
- 'float': 'float:4',
- 'double': 'float:8',
- 'QChar': 'uint:2'
- }.get(self.name, None)
- return res
+ return self.dumper.type_template_arguments(self.typeid)
+
+ def templateArgument(self, index):
+ return self.dumper.type_template_argument(self.typeid, index)
def isSimpleType(self):
return self.code in (TypeCode.Integral, TypeCode.Float, TypeCode.Enum)
def alignment(self):
- if self.tdata.code == TypeCode.Typedef:
- return self.ltarget.alignment()
- if self.tdata.code in (TypeCode.Integral, TypeCode.Float, TypeCode.Enum):
- if self.tdata.name in ('double', 'long long', 'unsigned long long'):
- # Crude approximation.
- return 8 if self.dumper.isWindowsTarget() else self.dumper.ptrSize()
- return self.size()
- if self.tdata.code in (TypeCode.Pointer, TypeCode.Reference, TypeCode.RValueReference):
- return self.dumper.ptrSize()
- if self.tdata.lalignment is not None:
- #if isinstance(self.tdata.lalignment, function): # Does not work that way.
- if hasattr(self.tdata.lalignment, '__call__'):
- return self.tdata.lalignment()
- return self.tdata.lalignment
- return 1
+ return self.dumper.type_alignment(self.typeid)
def pointer(self):
- return self.dumper.createPointerType(self)
-
- def target(self):
- return self.ltarget
+ return self.dumper.Type(self.dumper, self.dumper.create_pointer_typeid(self.typeid))
def stripTypedefs(self):
- if isinstance(self, self.dumper.Type) and self.code != TypeCode.Typedef:
- #DumperBase.warn('NO TYPEDEF: %s' % self)
- return self
- return self.ltarget
-
- def size(self):
- bs = self.lbitsize
- if bs % 8 != 0:
- DumperBase.warn('ODD SIZE: %s' % self)
- return (7 + bs) >> 3
-
- def bitsize(self):
- if self.lbitsize is not None:
- return self.lbitsize
- raise RuntimeError('DONT KNOW SIZE: %s' % self)
+ return self.dumper.Type(self.dumper, self.dumper.type_target(self.typeid))
def isMovableType(self):
if self.code in (TypeCode.Pointer, TypeCode.Integral, TypeCode.Float):
@@ -3748,264 +3409,195 @@ class DumperBase():
return self.dumper.qtVersion() >= 0x050600
return False
- class Field(collections.namedtuple('Field',
- ['dumper', 'name', 'type', 'bitsize', 'bitpos',
- 'extractor', 'isBase', 'isStruct', 'isArtificial'])):
+ class Field:
+ __slots__ = ['name', 'typeid', 'bitsize', 'bitpos', 'is_struct', 'is_artificial', 'is_base_class']
- def __new__(cls, dumper, name=None, type=None, bitsize=None, bitpos=None,
- extractor=None, isBase=False, isStruct=False, isArtificial=False):
- return super(DumperBase.Field, cls).__new__(
- cls, dumper, name, type, bitsize, bitpos,
- extractor, isBase, isStruct, isArtificial)
+ def __init__(self, name=None, typeid=None, bitsize=None, bitpos=None,
+ extractor=None, is_struct=False, is_artificial=False, is_base_class=False):
+ self.name = name
+ self.typeid = typeid
+ self.bitsize = bitsize
+ self.bitpos = bitpos
+ self.is_struct = is_struct
+ self.is_base_class = is_base_class
- __slots__ = ()
-
- def __str__(self):
- return self.stringify()
-
- def stringify(self):
- #return 'Field(name="%s")' % self.name
- typename = None if self.type is None else self.type.stringify()
- return 'Field(name="%s",type=%s,bitpos=%s,bitsize=%s)' \
- % (self.name, typename, self.bitpos, self.bitsize)
-
- def check(self):
- pass
-
- def size(self):
- return self.bitsize() // 8
-
- def offset(self):
- return self.bitpos // 8
-
- def fieldType(self):
- if self.type is not None:
- return self.type
- raise RuntimeError('CANT GET FIELD TYPE FOR %s' % self)
- return None
def ptrCode(self):
return 'I' if self.ptrSize() == 4 else 'Q'
- def toPointerData(self, address):
- if not self.isInt(address):
- raise RuntimeError('wrong')
- return bytes(struct.pack(self.packCode + self.ptrCode(), address))
-
def fromPointerData(self, bytes_value):
return struct.unpack(self.packCode + self.ptrCode(), bytes_value)
- def createPointerValue(self, targetAddress, targetTypish):
- if not isinstance(targetTypish, self.Type) and not isinstance(targetTypish, str):
- raise RuntimeError('Expected type in createPointerValue(), got %s'
- % type(targetTypish))
- if not self.isInt(targetAddress):
+ def createPointerValue(self, target_address, target_typish):
+ if not isinstance(target_address, int):
raise RuntimeError('Expected integral address value in createPointerValue(), got %s'
- % type(targetTypish))
+ % type(target_typish))
val = self.Value(self)
- val.ldata = self.toPointerData(targetAddress)
- targetType = self.createType(targetTypish)
- if self.useDynamicType:
- targetType = targetType.dynamicType(targetAddress)
- val._type = self.createPointerType(targetType)
+ val.ldata = target_address
+ val.typeid = self.create_pointer_typeid(self.create_typeid(target_typish))
return val
-
- def createReferenceValue(self, targetAddress, targetType):
- if not isinstance(targetType, self.Type):
- raise RuntimeError('Expected type in createReferenceValue(), got %s'
- % type(targetType))
- if not self.isInt(targetAddress):
- raise RuntimeError('Expected integral address value in createReferenceValue(), got %s'
- % type(targetType))
- val = self.Value(self)
- val.ldata = self.toPointerData(targetAddress)
- if self.useDynamicType:
- targetType = targetType.dynamicType(targetAddress)
- val._type = self.createReferenceType(targetType)
- return val
-
- def createPointerType(self, targetType):
- if not isinstance(targetType, (str, self.Type)):
- raise RuntimeError('Expected type or str in createPointerType(), got %s'
- % type(targetType))
- typeId = (targetType if isinstance(targetType, str) else targetType.typeId) + ' *'
- tdata = self.TypeData(self, typeId)
- tdata.name = (targetType if isinstance(targetType, str) else targetType.name) + '*'
- tdata.lbitsize = 8 * self.ptrSize()
- tdata.code = TypeCode.Pointer
- tdata.ltarget = targetType
- return self.Type(self, typeId)
-
- def createReferenceType(self, targetType):
- if not isinstance(targetType, self.Type):
- raise RuntimeError('Expected type in createReferenceType(), got %s'
- % type(targetType))
- typeId = targetType.typeId + ' &'
- tdata = self.TypeData(self, typeId)
- tdata.name = targetType.name + ' &'
- tdata.code = TypeCode.Reference
- tdata.ltarget = targetType
- tdata.lbitsize = 8 * self.ptrSize() # Needed for Gdb13393 test.
- #tdata.lbitsize = None
- return self.Type(self, typeId)
-
- def createRValueReferenceType(self, targetType):
- if not isinstance(targetType, self.Type):
- raise RuntimeError('Expected type in createRValueReferenceType(), got %s'
- % type(targetType))
- typeId = targetType.typeId + ' &&'
- tdata = self.TypeData(self, typeId)
- tdata.name = targetType.name + ' &&'
- tdata.code = TypeCode.RValueReference
- tdata.ltarget = targetType
- tdata.lbitsize = None
- return self.Type(self, typeId)
-
- def createArrayType(self, targetType, count):
- if not isinstance(targetType, self.Type):
- raise RuntimeError('Expected type in createArrayType(), got %s'
- % type(targetType))
- targetTypeId = targetType.typeId
-
- if targetTypeId.endswith(']'):
- (prefix, suffix, inner_count) = self.splitArrayType(targetTypeId)
- type_id = '%s[%d][%d]%s' % (prefix, count, inner_count, suffix)
- type_name = type_id
+ #target_typeid = self.create_typeid(target_typish)
+ #if self.useDynamicType:
+ # target_typeid = self.dynamic_typeid_at_address(target_typeid, target_address)
+ #val.typeid = self.create_pointer_typeid(target_typeid)
+ #return val
+
+ def createPointerType(self, target_typish):
+ typeid = self.create_pointer_typeid(self.typeid_for_typish(target_typish))
+ return self.Type(self, typeid)
+
+ def create_pointer_typeid(self, target_typeid):
+ name = self.type_name(target_typeid) + ' *'
+ typeid = self.typeid_for_string(name)
+ self.type_size_cache[typeid] = self.ptrSize()
+ self.type_alignment_cache[typeid] = self.ptrSize()
+ self.type_code_cache[typeid] = TypeCode.Pointer
+ self.type_target_cache[typeid] = target_typeid
+ return typeid
+
+ def create_reference_typeid(self, target_typeid):
+ type_name = self.type_name_cache[target_typeid] + ' &'
+ typeid = self.typeid_for_string(type_name)
+ self.type_code_cache[typeid] = TypeCode.Reference
+ self.type_target_cache[typeid] = target_typeid
+ #self.type_size_cache[typeid] = self.ptrSize() # Needed for Gdb13393 test.
+ return typeid
+
+ def create_rvalue_reference_typeid(self, target_typeid):
+ type_name = self.type_name_cache[target_typeid] + ' &&'
+ typeid = self.typeid_for_string(type_name)
+ self.type_code_cache[typeid] = TypeCode.RValueReference
+ self.type_target_cache[typeid] = target_typeid
+ return typeid
+
+ def create_array_typeid(self, target_typeid, count):
+ target_type_name = self.type_name(target_typeid)
+ if target_type_name.endswith(']'):
+ (prefix, suffix, inner_count) = self.splitArrayType(target_type_name)
+ type_name = '%s[%d][%d]%s' % (prefix, count, inner_count, suffix)
else:
- type_id = '%s[%d]' % (targetTypeId, count)
- type_name = '%s[%d]' % (targetType.name, count)
-
- tdata = self.TypeData(self, type_id)
- tdata.name = type_name
- tdata.code = TypeCode.Array
- tdata.ltarget = targetType
- tdata.lbitsize = targetType.lbitsize * count
- return self.Type(self, type_id)
-
- def createBitfieldType(self, targetType, bitsize):
- if not isinstance(targetType, self.Type):
- raise RuntimeError('Expected type in createBitfieldType(), got %s'
- % type(targetType))
- typeId = '%s:%d' % (targetType.typeId, bitsize)
- tdata = self.TypeData(self, typeId)
- tdata.name = '%s : %d' % (targetType.typeId, bitsize)
- tdata.code = TypeCode.Bitfield
- tdata.ltarget = targetType
- tdata.lbitsize = bitsize
- return self.Type(self, typeId)
-
- def createTypedefedType(self, targetType, typeName, typeId=None):
- if typeId is None:
- typeId = typeName
- if not isinstance(targetType, self.Type):
- raise RuntimeError('Expected type in createTypedefType(), got %s'
- % type(targetType))
+ type_name = '%s[%d]' % (target_type_name, count)
+ typeid = self.typeid_for_string(type_name)
+ self.type_code_cache[typeid] = TypeCode.Array
+ self.type_target_cache[typeid] = target_typeid
+ self.type_size_cache[typeid] = self.type_size(target_typeid) * count
+ self.type_alignment_cache[typeid] = self.type_alignment_cache.get(target_typeid, None)
+ return typeid
+
+ def create_bitfield_typeid(self, target_typeid, bitsize):
+ target_typename = self.type_name(target_typeid)
+ typeid = self.typeid_for_string('%s:%d' % (target_typename, bitsize))
+ self.type_name_cache[typeid] = '%s : %d' % (target_typename, bitsize)
+ self.type_code_cache[typeid] = TypeCode.Bitfield
+ self.type_target_cache[typeid] = target_typeid
+ self.type_bitsize_cache[typeid] = bitsize
+ return typeid
+
+ def create_typedefed_typeid(self, target_typeid, type_name, type_key):
+ typeid = self.typeid_for_string(type_key, type_name)
# Happens for C-style struct in GDB: typedef { int x; } struct S1;
- if targetType.typeId == typeId:
- return targetType
- tdata = self.TypeData(self, typeId)
- tdata.name = typeName
- tdata.code = TypeCode.Typedef
- tdata.ltarget = targetType
- tdata.lbitsize = targetType.lbitsize
- #tdata.lfields = targetType.lfields
- tdata.lbitsize = targetType.lbitsize
- return self.Type(self, typeId)
-
- def knownArrayTypeSize(self):
- return 3 * self.ptrSize() if self.qtVersion() >= 0x060000 else self.ptrSize()
-
- def knownTypeSize(self, typish):
- if typish[0] == 'Q':
- if typish.startswith('QList<') or typish.startswith('QVector<'):
- return self.knownArrayTypeSize()
- if typish == 'QObject':
- return 2 * self.ptrSize()
- if typish == 'QStandardItemData':
- return 4 * self.ptrSize() if self.qtVersion() >= 0x060000 else 2 * self.ptrSize()
- if typish == 'Qt::ItemDataRole':
- return 4
- if typish == 'QChar':
- return 2
- if typish in ('quint32', 'qint32'):
- return 4
- return None
+ if target_typeid == typeid:
+ return target_typeid
+ self.type_code_cache[typeid] = TypeCode.Typedef
+ self.type_target_cache[typeid] = target_typeid
+ self.type_size_cache[typeid] = self.type_size_cache.get(target_typeid, None)
+ return typeid
def createType(self, typish, size=None):
- if isinstance(typish, self.Type):
- #typish.check()
- if hasattr(typish, 'lbitsize') and typish.lbitsize is not None and typish.lbitsize > 0:
- return typish
- # Size 0 is sometimes reported by GDB but doesn't help at all.
- # Force using the fallback:
- typish = typish.name
+ return self.Type(self, self.create_typeid(typish, size))
+ def create_typeid(self, typish, size=None):
+ if isinstance(typish, int):
+ return typish
+ if isinstance(typish, self.Type):
+ return typish.typeid
if isinstance(typish, str):
- ns = self.qtNamespace()
- typish = typish.replace('@', ns)
- if typish.startswith(ns):
- if size is None:
- size = self.knownTypeSize(typish[len(ns):])
- else:
- if size is None:
- size = self.knownTypeSize(typish)
- if size is not None:
- typish = ns + typish
-
- tdata = self.typeData.get(typish, None)
- if tdata is not None:
- if tdata.lbitsize is not None:
- if callable(tdata.lbitsize) or tdata.lbitsize > 0:
- return self.Type(self, typish)
-
- knownType = self.lookupType(typish)
- #DumperBase.warn('KNOWN: %s' % knownType)
- if knownType is not None:
- #DumperBase.warn('USE FROM NATIVE')
- return knownType
-
- #DumperBase.warn('FAKING: %s SIZE: %s' % (typish, size))
- tdata = self.TypeData(self, typish)
- tdata.templateArguments = lambda: self.listTemplateParameters(typish)
- if size is not None:
- tdata.lbitsize = 8 * size
- if typish.endswith('*'):
- tdata.code = TypeCode.Pointer
- tdata.lbitsize = 8 * self.ptrSize()
- tdata.ltarget = typish[:-1].strip()
-
- typeobj = self.Type(self, tdata.typeId)
- #DumperBase.warn('CREATE TYPE: %s' % typeobj.stringify())
- typeobj.check()
- return typeobj
+ return self.create_typeid_from_name(typish)
raise RuntimeError('NEED TYPE, NOT %s' % type(typish))
- def createValueFromAddressAndType(self, address, typish):
+ def cheap_typeid_from_name(self, typename_):
+ ns = self.qtNamespace()
+ typename = typename_.replace('@', ns)
+ return self.cheap_typeid_from_name_nons(typename)
+
+ def cheap_typeid_from_name_nons(self, typename):
+ if typename in self.typeid_cache:
+ return self.typeid_for_string(typename)
+
+ if typename.startswith('QList<') or typename.startswith('QVector<'):
+ typeid = self.typeid_for_string(typename)
+ if typeid:
+ size = 3 * self.ptrSize() if self.qtVersion() >= 0x060000 else self.ptrSize()
+ self.type_code_cache[typeid] = TypeCode.Struct
+ self.type_size_cache[typeid] = size
+ return typeid
+
+ if typename.endswith('*'):
+ inner_typeid = self.cheap_typeid_from_name_nons(typename[0:-1])
+ if inner_typeid != 0:
+ return self.create_pointer_typeid(inner_typeid)
+
+ return 0
+
+ def create_typeid_from_name(self, typename_, size=None):
+ ns = self.qtNamespace()
+ typename = typename_.replace('@', ns)
+
+ if typename in self.typeid_cache:
+ return self.typeid_for_string(typename)
+
+ # This triggers for boost::variant<int, std::string> due to the mis-encoding
+ # of the second template parameter. [MARK_A]
+ knownType = self.lookupType(typename)
+ #self.warn('KNOWN: %s FOR %s' % (knownType, typename))
+ if knownType is not None:
+ #self.warn('USE FROM NATIVE')
+ #self.dump_location()
+ return knownType.typeid
+
+ #self.warn('FAKING: %s SIZE: %s' % (typename, size))
+ typeid = self.typeid_for_string(typename)
+ if size is not None:
+ self.type_size_cache[typeid] = size
+ self.type_code_cache[typeid] = TypeCode.Struct
+ if typename.endswith('*'):
+ self.type_code_cache[typeid] = TypeCode.Pointer
+ self.type_size_cache[typeid] = self.ptrSize()
+ self.type_target_cache[typeid] = self.typeid_for_string(typename[:-1].strip())
+
+ #self.dump_location()
+ #self.warn('CREATED TYPE: %s' % typeid)
+ return typeid
+
+ def createValueFromAddress(self, address, typish):
val = self.Value(self)
- val._type = self.createType(typish)
- #DumperBase.warn('CREATING %s AT 0x%x' % (val.type.name, datish))
+ val.typeid = self.create_typeid(typish)
+ #self.warn('CREATING %s AT 0x%x' % (val.type.name, address))
val.laddress = address
if self.useDynamicType:
- val._type = val.type.dynamicType(address)
+ val.typeid = self.dynamic_typeid_at_address(val.typeid, address)
+ return val
+
+ def createValueFromData(self, data, typish):
+ val = self.Value(self)
+ val.typeid = self.create_typeid(typish)
+ #self.warn('CREATING %s WITH DATA %s' % (val.type.name, self.hexencode(data)))
+ val.ldata = data
+ val.check()
return val
def createValue(self, datish, typish):
- if self.isInt(datish): # Used as address.
- return self.createValueFromAddressAndType(datish, typish)
+ if isinstance(datish, int): # Used as address.
+ return self.createValueFromAddress(datish, typish)
if isinstance(datish, bytes):
- val = self.Value(self)
- val._type = self.createType(typish)
- #DumperBase.warn('CREATING %s WITH DATA %s' % (val.type.name, self.hexencode(datish)))
- val.ldata = datish
- val.check()
- return val
+ return self.createValueFromData(datish, typish)
raise RuntimeError('EXPECTING ADDRESS OR BYTES, GOT %s' % type(datish))
def createProxyValue(self, proxy_data, type_name):
- tdata = self.TypeData(self, type_name)
- tdata.code = TypeCode.Struct
+ typeid = self.typeid_for_string(type_name)
+ self.type_code_cache[typeid] = TypeCode.Struct
val = self.Value(self)
- val._type = self.Type(self, type_name)
+ val.typeid = typeid
val.ldata = proxy_data
return val
@@ -4013,109 +3605,667 @@ class DumperBase():
def __init__(self, dumper):
self.dumper = dumper
self.pattern = ''
- self.currentBitsize = 0
+ self.current_size = 0
self.fields = []
self.autoPadNext = False
self.maxAlign = 1
- def addField(self, fieldSize, fieldCode=None, fieldIsStruct=False,
- fieldName=None, fieldType=None, fieldAlign=1):
+ def add_field(self, field_size, field_code=None, field_is_struct=False,
+ field_name=None, field_typeid=0, field_align=1):
+
+ if field_code is None:
+ field_code = '%ss' % field_size
- if fieldType is not None:
- fieldType = self.dumper.createType(fieldType)
- if fieldSize is None and fieldType is not None:
- fieldSize = fieldType.size()
- if fieldCode is None:
- fieldCode = '%ss' % fieldSize
+ #self.dumper.warn("FIELD SIZE: %s %s %s " % (field_name, field_size, str(field_align)))
if self.autoPadNext:
- self.currentBitsize = 8 * ((self.currentBitsize + 7) >> 3) # Fill up byte.
- padding = (fieldAlign - (self.currentBitsize >> 3)) % fieldAlign
- #DumperBase.warn('AUTO PADDING AT %s BITS BY %s BYTES' % (self.currentBitsize, padding))
- field = self.dumper.Field(self.dumper, bitpos=self.currentBitsize,
+ padding = (field_align - self.current_size) % field_align
+ #self.warn('AUTO PADDING AT %s BITS BY %s BYTES' % (self.current_size, padding))
+ field = self.dumper.Field(self.dumper, bitpos=self.current_size * 8,
bitsize=padding * 8)
self.pattern += '%ds' % padding
- self.currentBitsize += padding * 8
+ self.current_size += padding
self.fields.append(field)
self.autoPadNext = False
- if fieldAlign > self.maxAlign:
- self.maxAlign = fieldAlign
- #DumperBase.warn("MAX ALIGN: %s" % self.maxAlign)
+ if field_align > self.maxAlign:
+ self.maxAlign = field_align
- field = self.dumper.Field(dumper=self.dumper, name=fieldName, type=fieldType,
- isStruct=fieldIsStruct, bitpos=self.currentBitsize,
- bitsize=fieldSize * 8)
+ #self.warn("MAX ALIGN: %s" % self.maxAlign)
- self.pattern += fieldCode
- self.currentBitsize += fieldSize * 8
+ field = self.dumper.Field(name=field_name, typeid=field_typeid,
+ is_struct=field_is_struct, bitpos=self.current_size *8,
+ bitsize=field_size * 8)
+
+ self.pattern += field_code
+ self.current_size += field_size
self.fields.append(field)
+ def describe_struct_member(self, typename):
+ typename = typename.replace('@', self.qtNamespace())
+
+ typeid = self.cheap_typeid_from_name_nons(typename)
+ if typeid:
+ size = self.type_size_cache.get(typeid, None)
+ if size is not None:
+ return size, typeid
+
+ typeobj = self.lookupType(typename)
+ self.warn("LOOKUP FIELD TYPE: %s TYPEOBJ: %s" % (typename, typeobj))
+ if typeobj is not None:
+ typeid = typeobj.typeid
+ size = self.type_size_cache.get(typeid, None)
+ if size is not None:
+ return size, typeid
+
+ self.warn("UNKNOWN EMBEDDED TYPE: %s" % typename)
+ return 0, 0
+
+ @functools.lru_cache(maxsize = None)
def describeStruct(self, pattern):
- if pattern in self.structPatternCache:
- return self.structPatternCache[pattern]
ptrSize = self.ptrSize()
builder = self.StructBuilder(self)
n = None
- typeName = ''
+ typename = ''
readingTypeName = False
+ #self.warn("PATTERN: %s" % pattern)
for c in pattern:
+ #self.warn("PAT CODE: %s %s" % (c, str(n)))
if readingTypeName:
if c == '}':
readingTypeName = False
- fieldType = self.createType(typeName)
- fieldAlign = fieldType.alignment()
- builder.addField(n, fieldIsStruct=True,
- fieldType=fieldType, fieldAlign=fieldAlign)
- typeName = None
+ n, field_typeid = self.describe_struct_member(typename)
+
+ field_align = self.type_alignment(field_typeid)
+ builder.add_field(n,
+ field_is_struct=True,
+ field_typeid=field_typeid,
+ field_align=field_align)
+ typename = None
n = None
else:
- typeName += c
+ typename += c
elif c == 't': # size_t
- builder.addField(ptrSize, self.ptrCode(), fieldAlign=ptrSize)
+ builder.add_field(ptrSize, self.ptrCode(), field_align=ptrSize)
elif c == 'p': # Pointer as int
- builder.addField(ptrSize, self.ptrCode(), fieldAlign=ptrSize)
+ builder.add_field(ptrSize, self.ptrCode(), field_align=ptrSize)
elif c == 'P': # Pointer as Value
- builder.addField(ptrSize, '%ss' % ptrSize, fieldAlign=ptrSize)
+ builder.add_field(ptrSize, '%ss' % ptrSize, field_align=ptrSize)
elif c in ('d'):
- builder.addField(8, c, fieldAlign=ptrSize) # fieldType = 'double' ?
+ builder.add_field(8, c, field_align=ptrSize) # field_type = 'double' ?
elif c in ('q', 'Q'):
- builder.addField(8, c, fieldAlign=ptrSize)
+ builder.add_field(8, c, field_align=ptrSize)
elif c in ('i', 'I', 'f'):
- builder.addField(4, c, fieldAlign=4)
+ builder.add_field(4, c, field_align=4)
elif c in ('h', 'H'):
- builder.addField(2, c, fieldAlign=2)
+ builder.add_field(2, c, field_align=2)
elif c in ('b', 'B', 'c'):
- builder.addField(1, c, fieldAlign=1)
+ builder.add_field(1, c, field_align=1)
elif c >= '0' and c <= '9':
if n is None:
n = ''
n += c
elif c == 's':
- builder.addField(int(n), fieldAlign=1)
+ builder.add_field(int(n), field_align=1)
n = None
elif c == '{':
readingTypeName = True
- typeName = ''
+ typename = ''
elif c == '@':
if n is None:
# Automatic padding depending on next item
builder.autoPadNext = True
else:
# Explicit padding.
- builder.currentBitsize = 8 * ((builder.currentBitsize + 7) >> 3)
- padding = (int(n) - (builder.currentBitsize >> 3)) % int(n)
+ padding = (int(n) - builder.current_size) % int(n)
field = self.Field(self)
builder.pattern += '%ds' % padding
- builder.currentBitsize += padding * 8
+ builder.current_size += padding
builder.fields.append(field)
n = None
else:
raise RuntimeError('UNKNOWN STRUCT CODE: %s' % c)
pp = builder.pattern
- size = (builder.currentBitsize + 7) >> 3
+ size = builder.current_size
fields = builder.fields
tailPad = (builder.maxAlign - size) % builder.maxAlign
size += tailPad
- self.structPatternCache[pattern] = (pp, size, fields)
+ #self.warn("FIELDS: %s" % ((pp, size, fields),))
return (pp, size, fields)
+
+ def type_stringify(self, typeid):
+ return 'Type(id="%s",name="%s",bsize=%s,code=%s)'% (
+ str(typeid),
+ self.type_name_cache.get(typeid, '?'),
+ self.type_bitsize_cache.get(typeid, '?'),
+ self.type_code_cache.get(typeid, '?'))
+
+ def type_name(self, typeid):
+ name = self.type_name_cache.get(typeid, None)
+ if name is None:
+ self.dump_type_cache()
+ self.check_typeid(typeid)
+ raise RuntimeError('UNNAMED TYPE: %d' % typeid)
+ return name
+
+ def type_code(self, typeid):
+ # This does not seem to be needed for GDB and LLDB
+ if not typeid in self.type_code_cache:
+ typename = self.type_name_cache.get(typeid, None)
+ if typename is None:
+ raise RuntimeError('NAME/ID ERROR FOR %s' % typeid)
+ #self.warn("EMERGENCY LOOKUP: %s " % typename)
+ typeobj = self.lookupType(typename)
+ if typeobj is None:
+ #self.warn("EMERGENCY LOOKUP FAILED: %s " % typeid)
+ #self.dump_type_cache()
+ return TypeCode.Struct
+ #self.warn("EMERGENCY LOOKUP SUCCEEDED: %s " % typeid)
+ typeid = typeobj.typeid
+ return self.type_code_cache[typeid]
+
+ def type_bitpos(self, typeid):
+ return self.type_bitpos_cache[typeid]
+
+ def type_target(self, typeid):
+ return self.type_target_cache.get(typeid, None)
+ targetid = self.type_target_cache.get(typeid, None)
+ if not targetid in self.type_code_cache:
+ typename = self.type_name_cache.get(targetid, None)
+ if typename is None:
+ raise RuntimeError('NAME/ID ERROR FOR TARGET %s' % targetid)
+ typeobj = self.lookupType(typename)
+ if typeobj is None:
+ #self.warn("EMERGENCY LOOKUP FAILED FOR %s %s " % (typename, typeid))
+ #self.dump_type_cache()
+ return 0 # Void type id
+ return targetid
+
+ def type_template_arguments(self, typeid):
+ targs = []
+ #self.dump_type_cache()
+ #self.warn('TRY TEMPLATE ARGS FOR %s' % typeid)
+ for index in range(0, 100):
+ targ = self.type_template_argument(typeid, index)
+ #self.warn('INDEX %s %s' % (index, targ))
+ if targ is None:
+ break
+ targs.append(targ)
+ #self.warn('TARGS %s' % targs)
+ return targs
+
+ def nativeTemplateParameter(self, typeid, index, nativeType):
+ return None
+
+ def type_template_argument(self, typeid, index):
+ targ = self.type_template_arguments_cache.get((typeid, index), None)
+ if targ is not None:
+ return targ
+
+ native_type = self.type_nativetype_cache.get(typeid, None)
+ if native_type is not None:
+ targ = self.nativeTemplateParameter(typeid, index, native_type)
+ if targ is not None:
+ self.type_template_arguments_cache[(typeid, index)] = targ
+ return targ
+
+ # FIXME: The block below is apparently not needed anymore in the GDB
+ # and LLDB cases, so removing also doesn't bring performance. But it
+ # is at least potentially one source of type lookups.
+ #typename = self.type_name(typeid)
+ #self.dump_type_cache()
+ #self.warn('TEMPLATE ARGS FOR %s %s' % (typeid, typename))
+ #typeobj = self.lookupType(typename)
+ #if typeobj is not None:
+ # #self.warn(' FOUNT NATIVE %s %s, %s' % (typeid, typeobj, native_type))
+ # native_type = self.type_nativetype_cache.get(typeobj.typeid, None)
+ # #targ = self.type_template_argument(typeobj.typeid, index)
+ # targ = self.nativeTemplateParameter(typeobj.typeid, index, native_type)
+ # if targ is not None:
+ # self.type_template_arguments_cache[(typeid, index)] = targ
+ # return targ
+
+ # Native lookups didn't help. Happens for 'wrong' placement of 'const'
+ # etc. with LLDB or template parameter packs with gcc in boost::variant
+ # 13.2.0. But not all is lost:
+ self.fill_template_parameters_manually(typeid)
+ targ = self.type_template_arguments_cache.get((typeid, index), None)
+ return targ
+
+ def type_alignment(self, typeid):
+ alignment = self.type_alignment_cache.get(typeid, None)
+ if alignment is not None:
+ return alignment
+
+ code = self.type_code_cache.get(typeid, None)
+ if code in (TypeCode.Typedef, TypeCode.Array):
+ alignment = self.type_alignment(self.type_target_cache[typeid])
+ elif code in (TypeCode.Integral, TypeCode.Float, TypeCode.Enum):
+ name = self.type_name(typeid)
+ if name in ('double', 'long long', 'unsigned long long'):
+ # Crude approximation.
+ alignment = 8 if self.isWindowsTarget() else self.ptrSize()
+ else:
+ alignment = self.type_size(typeid)
+ elif code in (TypeCode.Pointer, TypeCode.Reference, TypeCode.RValueReference):
+ alignment = self.ptrSize()
+ elif self.isCdb:
+ alignment = self.nativeStructAlignment(self.type_nativetype(typeid))
+ else:
+ size = self.type_size(typeid)
+ if size is None:
+ self.dump_type_cache()
+ self.warn("NO ALIGNMENT FOUND FOR SIZE OF TYPE %s" % str(typeid))
+ return 1
+ if size >= self.ptrSize():
+ alignment = self.ptrSize()
+ else:
+ alignment = size
+ #self.warn("GUESSING ALIGNMENT %s FOR TYPEID %s" % (alignment, typeid))
+ self.type_alignment_cache[typeid] = alignment
+ return alignment
+
+
+ def type_nativetype(self, typeid):
+ native_type = self.type_nativetype_cache.get(typeid, None)
+ if native_type is not None:
+ return native_type
+
+ typename = self.type_name(typeid)
+ native_type = self.lookupNativeType(typename)
+ # Also cache unsuccessful attempts
+ self.type_nativetype_cache[typeid] = native_type
+
+ return native_type
+
+
+ def type_size(self, typeid):
+ self.check_typeid(typeid)
+ size = self.type_size_cache.get(typeid, None)
+ if size is not None:
+ return size
+
+ if size is None:
+ nativeType = self.type_nativetype(typeid)
+ if not self.type_size_cache.get(typeid):
+ self.from_native_type(nativeType)
+ size = self.type_size_cache.get(typeid, None)
+
+ if size is not None:
+ self.type_size_cache[typeid] = size
+ else:
+ self.dump_type_cache()
+ self.warn("CANNOT DETERMINE SIZE FOR TYPE %s" % str(typeid))
+
+ return size
+
+ def type_bitsize(self, typeid):
+ bitsize = self.type_bitsize_cache.get(typeid, None)
+ if bitsize is None:
+ bitsize = 8 * self.type_size(typeid)
+ self.type_bitsize_cache[typeid] = bitsize
+ return bitsize
+
+ def dynamic_typeid_at_address(self, base_typeid, address):
+ #with self.dumper.timer('dynamic_typeid_at_address %s 0x%s' % (self.name, address)):
+ type_code = self.type_code_cache.get(base_typeid, None)
+ if type_code != TypeCode.Struct:
+ #self.dump_type_cache()
+ #self.warn('SHORT CUT FOR BASE ID: %d TC: %s' % (base_typeid, type_code))
+ return base_typeid
+
+ # This turned out to be expensive.
+ #try:
+ # vtbl = self.extract_pointer_at_address(address)
+ #except:
+ # return base_typeid
+ ##self.warn('VTBL: 0x%x' % vtbl)
+ #if not self.couldBePointer(vtbl):
+ # return base_typeid
+ #self.warn("DYN TYPE FOR %s %s" % (base_typeid, self.type_name(base_typeid)))
+
+ return self.nativeDynamicType(address, base_typeid)
+
+ # This is the generic version for synthetic values.
+ # The native backends replace it in their fromNativeValue()
+ # implementations.
+ def value_members(self, value, include_bases):
+ #self.warn("LISTING MEMBERS OF %s" % value)
+ #self.warn("LISTING MEMBERS OF TYPE %s %s" % (value.typeid, self.type_name(value.typeid)))
+ typeid = value.typeid
+
+ members = self.type_fields_cache.get(typeid, None)
+ if members is not None:
+ return members
+
+ members = []
+ native_type = self.type_nativetype_cache.get(typeid, None)
+ if native_type is None:
+ native_type = self.lookupNativeType(self.type_name(typeid))
+ if not native_type is None:
+ members = self.nativeListMembers(value, native_type, include_bases)
+ #self.warn("FIELDS 2: %s" % ', '.join(str(f) for f in members))
+ else:
+ self.warn("NO NATIVE TYPE FIELDS FOR: %s" % typeid)
+
+ #self.warn("GOT MEMBERS: %s" % ', '.join(str(f.name) for f in members))
+ return members
+
+ def value_member_by_field(self, value, field):
+ #self.warn("EXTRACTING MEMBER '%s' OF %s AT OFFSET %s" % (field.name, field.typeid, field.bitpos))
+ val = self.Value(self)
+ val.typeid = field.typeid
+ val.name = field.name
+ val.isBaseClass = field.is_base_class
+ #self.warn('CREATING %s WITH DATA %s' % (val.type.name, self.hexencode(data)))
+ field_offset = field.bitpos // 8
+ if value.laddress is not None:
+ val.laddress = value.laddress + field_offset
+ field_size = (field.bitsize + 7) // 8
+ blob = self.value_data(value, field_offset + field_size)
+ val.ldata = blob[field_offset:field_offset + field_size]
+ #self.dump_location()
+ return val
+
+ def value_member_by_name(self, value, name):
+ #field = self.type_fields_cache.get((value.typeid, name), None)
+ #if field is not None:
+ # return self.value_member_by_field(value, field)
+
+ #self.dump_location()
+ #self.warn("WANT MEMBER '%s' OF '%s'" % (name, value))
+ #value.check()
+ value_typecode = self.type_code(value.typeid)
+ if value_typecode == TypeCode.Typedef:
+ return self.value_member_by_name(self.value_detypedef(value), name)
+ if value_typecode in (TypeCode.Pointer, TypeCode.Reference, TypeCode.RValueReference):
+ res = self.value_member_by_name(self.value_dereference(value), name)
+ if res is not None:
+ return res
+ if value_typecode == TypeCode.Struct:
+ #self.warn('SEARCHING FOR MEMBER: %s IN %s' % (name, value.type.name))
+ members = self.value_members(value, True)
+ #self.warn('MEMBERS: %s' % ', '.join(str(m.name) for m in members))
+ base = None
+ for member in members:
+ #self.warn('CHECKING FIELD %s' % member.name)
+ if member.type.code == TypeCode.Typedef:
+ member = member.detypedef()
+ if member.name == name:
+ #self.warn('FOUND MEMBER 1: %s IN %s' % (name, value.type.name))
+ return member
+ if member.isBaseClass:
+ base = member
+ if self.isCdb:
+ if base is not None:
+ # self.warn("CHECKING BASE CLASS '%s' for '%s'" % (base.type.name, name))
+ res = self.value_member_by_name(base, name)
+ if res is not None:
+ # self.warn('FOUND MEMBER 2: %s IN %s' % (name, value.type.name))
+ return res
+ else:
+ for member in members:
+ if member.type.code == TypeCode.Typedef:
+ member = member.detypedef()
+ if member.name == name: # Could be base class.
+ return member
+ if member.type.code == TypeCode.Struct:
+ res = self.value_member_by_name(member, name)
+ if res is not None:
+ #self.warn('FOUND MEMBER 2: %s IN %s' % (name, value.type.name))
+ return res
+
+ #self.warn('DID NOT FIND MEMBER: %s IN %s' % (name, value.type.name))
+ #self.dump_location()
+ return None
+
+ def value_member_by_indexish(self, value, indexish):
+ #self.warn('GET ITEM %s %s' % (self, indexish))
+ #value.check()
+ value_typecode = self.type_code(value.typeid)
+ if isinstance(indexish, str):
+ if value_typecode == TypeCode.Pointer:
+ #self.warn('GET ITEM %s DEREFERENCE TO %s' % (value, value.dereference()))
+ return value.dereference().__getitem__(indexish)
+ res = self.value_member_by_name(value, indexish)
+ if res is None:
+ raise RuntimeError('No member named %s in type %s'
+ % (indexish, value.type.name))
+ return res
+ if isinstance(indexish, int):
+ if value_typecode == TypeCode.Array:
+ addr = value.laddress + int(indexish) * value.type.target().size()
+ return self.createValueFromAddress(addr, value.type.target())
+ if value_typecode == TypeCode.Pointer:
+ addr = value.pointer() + int(indexish) * value.type.target().size()
+ return self.createValueFromAddress(addr, value.type.target())
+ return self.value_members(value, False)[indexish]
+ raise RuntimeError('BAD INDEX TYPE %s' % type(indexish))
+
+ def value_extract_bits(self, value, bitpos, bitsize):
+ value_size = self.type_size(value.typeid)
+ ldata = bytes(self.value_data(value, value_size))
+ bdata = ''.join([format(x, '0>8b')[::-1] for x in ldata])
+ fdata = bdata[bitpos : bitpos + bitsize]
+ fdata = fdata[::-1]
+ return int(fdata, 2)
+
+ def value_display_enum(self, value, form='%d', bitsize=None):
+ size = value.type.size()
+ intval = self.value_extract_integer(value, size, False)
+ dd = self.type_enum_display_cache.get(value.typeid, None)
+ if dd is None:
+ return str(intval)
+ return dd(intval, value.laddress, form)
+
+ def value_as_address(self, value):
+ return self.value_extract_integer(value, self.ptrSize(), False)
+
+ def value_as_integer(self, value):
+ if isinstance(value.ldata, int):
+ return value.ldata
+ type_name = self.type_name(value.typeid)
+ signed = type_name != 'unsigned' \
+ and not type_name.startswith('unsigned ') \
+ and type_name.find(' unsigned ') == -1
+ size = value.type.size()
+ return self.value_extract_integer(value, size, signed)
+
+ def value_as_floating_point(self, value):
+ if value.nativeValue is not None and not self.isCdb:
+ return str(value.nativeValue)
+ if self.type_code(value.typeid) == TypeCode.Typedef:
+ return self.value_as_floating_point(self.value_detypedef(value))
+ if value.type.size() == 8:
+ blob = self.value_data(value, 8)
+ return struct.unpack_from(self.packCode + 'd', blob, 0)[0]
+ if value.type.size() == 4:
+ blob = self.value_data(value, 4)
+ return struct.unpack_from(self.packCode + 'f', blob, 0)[0]
+ # Fall back in case we don't have a nativeValue at hand.
+ # FIXME: This assumes Intel's 80bit extended floats. Which might
+ # be wrong.
+ l, h = value.split('QQ')
+ if True: # 80 bit floats
+ sign = (h >> 15) & 1
+ exp = (h & 0x7fff)
+ fraction = l
+ bit63 = (l >> 63) & 1
+ #self.warn("SIGN: %s EXP: %s H: 0x%x L: 0x%x" % (sign, exp, h, l))
+ if exp == 0:
+ if bit63 == 0:
+ if l == 0:
+ res = '-0' if sign else '0'
+ else:
+ res = (-1)**sign * l * 2**(-16382) # subnormal
+ else:
+ res = 'pseudodenormal'
+ elif exp == 0x7fff:
+ res = 'special'
+ else:
+ res = (-1)**sign * l * 2**(exp - 16383 - 63)
+ else: # 128 bits
+ sign = h >> 63
+ exp = (h >> 48) & 0x7fff
+ fraction = h & (2**48 - 1)
+ #self.warn("SIGN: %s EXP: %s FRAC: %s H: 0x%x L: 0x%x" % (sign, exp, fraction, h, l))
+ if exp == 0:
+ if fraction == 0:
+ res = -0.0 if sign else 0.0
+ else:
+ res = (-1)**sign * fraction / 2**48 * 2**(-62) # subnormal
+ elif exp == 0x7fff:
+ res = ('-inf' if sign else 'inf') if fraction == 0 else 'nan'
+ else:
+ res = (-1)**sign * (1 + fraction / 2**48) * 2**(exp - 63)
+ return res
+
+ def value_data(self, value, size):
+ if value.ldata is not None:
+ return value.ldata[:size]
+ if value.laddress is not None:
+ return self.value_data_from_address(value.laddress, size)
+ raise RuntimeError('CANNOT CONVERT TO BYTES: %s' % value)
+
+ def value_data_from_address(self, address, size):
+ if not isinstance(address, int):
+ raise RuntimeError('ADDRESS WRONG TYPE: %s' % type(address))
+ if not isinstance(size, int):
+ raise RuntimeError('SIZE WRONG TYPE: %s' % type(size))
+ if size <= 0:
+ raise RuntimeError('SIZE WRONG VALUE: %s' % size)
+ res = self.readRawMemory(address, size)
+ if len(res) > 0:
+ return res
+ raise RuntimeError('CANNOT READ %d BYTES FROM ADDRESS: %s %s' % (size, address))
+
+ def value_display(self, value):
+ type_code = self.type_code(value.typeid)
+ if type_code == TypeCode.Enum:
+ return self.value_display_enum(value)
+ if type_code == TypeCode.Typedef:
+ return self.value_display(self.value_detypedef(value))
+ if type_code == TypeCode.Integral:
+ return self.value_as_integer(value)
+ if type_code == TypeCode.Bitfield:
+ return self.value_as_integer(value)
+ if type_code == TypeCode.Float:
+ return self.value_as_floating_point(value)
+ if type_code == TypeCode.Pointer:
+ return self.value_as_address(value)
+ return None
+
+ def value_detypedef(self, value):
+ #value.check()
+ #if value.type.code != TypeCode.Typedef:
+ # raise RuntimeError("WRONG")
+ val = value.copy()
+ val.typeid = self.type_target(value.typeid)
+ #self.warn("DETYPEDEF FROM: %s" % self)
+ #self.warn("DETYPEDEF TO: %s" % val)
+ return val
+
+ def split(self, pattern, value_or_address):
+ if isinstance(value_or_address, self.Value):
+ return self.value_split(value_or_address, pattern)
+ if isinstance(value_or_address, int):
+ val = self.Value(self)
+ val.laddress = value_or_address
+ return self.value_split(val, pattern)
+ raise RuntimeError('CANNOT EXTRACT STRUCT FROM %s' % type(value_or_address))
+
+ def value_split(self, value, pattern):
+ #self.warn('EXTRACT STRUCT FROM: %s' % self.type)
+ (pp, size, fields) = self.describeStruct(pattern)
+ #self.warn('SIZE: %s ' % size)
+
+ blob = self.value_data(value, size)
+ address = value.laddress
+
+ parts = struct.unpack_from(self.packCode + pp, blob)
+
+ def fix_struct(field, part):
+ #self.warn('STRUCT MEMBER: %s' % type(part))
+ if field.is_struct:
+ res = self.Value(self)
+ res.typeid = field.typeid
+ res.ldata = part
+ if address is not None:
+ res.laddress = address + field.bitpos // 8
+ return res
+ return part
+
+ if len(fields) != len(parts):
+ raise RuntimeError('STRUCT ERROR: %s %s' % (fields, parts))
+ return tuple(map(fix_struct, fields, parts))
+
+ def type_dereference(self, typeid):
+ if self.type_code(typeid) == TypeCode.Typedef:
+ return self.type_dereference(self.type_target(typeid))
+ return self.type_target(typeid)
+
+ def type_strip_typedefs(self, typeid):
+ if self.type_code(typeid) == TypeCode.Typedef:
+ return self.type_strip_typedefs(self.type_target(typeid))
+ return typeid
+
+ def value_dereference(self, value):
+ value.check()
+ #if value.type.code == TypeCode.Typedef:
+ # return self.value_dereference(self.value_detypedef(value))
+ val = self.Value(self)
+ if value.type.code in (TypeCode.Reference, TypeCode.RValueReference):
+ val.summary = value.summary
+ if value.nativeValue is None:
+ val.laddress = value.pointer()
+ if val.laddress is None and value.laddress is not None:
+ val.laddress = value.laddress
+ val.typeid = self.type_dereference(value.typeid)
+ if self.useDynamicType:
+ val.typeid = self.nativeDynamicType(val.laddress, val.typeid)
+ else:
+ val = self.nativeValueDereferenceReference(value)
+ elif value.type.code == TypeCode.Pointer:
+ try:
+ val = self.nativeValueDereferencePointer(value)
+ except:
+ val.laddress = value.pointer()
+ val.typeid = self.type_dereference(value.typeid)
+ if self.useDynamicType:
+ val.typeid = self.nativeDynamicType(val.laddress, val.typeid)
+ else:
+ raise RuntimeError("WRONG: %s" % value.type.code)
+
+ return val
+
+ def value_cast(self, value, typish):
+ value.check()
+ val = self.Value(self)
+ val.laddress = value.laddress
+ val.ldata = value.ldata
+ val.typeid = self.create_typeid(typish)
+ return val
+
+ def value_plus_something(self, value, other):
+ value.check()
+ if isinstance(other, int):
+ stripped = self.type_strip_typedefs(value.typeid)
+ if self.type_code(stripped) == TypeCode.Pointer:
+ item_size = self.type_size(self.type_dereference(stripped))
+ address = self.value_as_address(value) + item_size * other
+ val = self.Value(self)
+ val.laddress = None
+ val.ldata = address
+ val.typeid = value.typeid
+ return val
+ raise RuntimeError('BAD DATA TO ADD TO: %s %s' % (value.type, other))
+
+ def value_minus_something(self, value, other):
+ value.check()
+ if other.type.name == value.type.name:
+ stripped = self.type_strip_typedefs(value.typeid)
+ if self.type_code(stripped.code) == TypeCode.Pointer:
+ item_size = self.type_size(self.type_dereference(stripped))
+ return (value.pointer() - other.pointer()) // item_size
+ raise RuntimeError('BAD DATA TO SUB TO: %s %s' % (value.type, other))
+
diff --git a/share/qtcreator/debugger/gdbbridge.py b/share/qtcreator/debugger/gdbbridge.py
index 9699e518fe..f30b0fbafa 100644
--- a/share/qtcreator/debugger/gdbbridge.py
+++ b/share/qtcreator/debugger/gdbbridge.py
@@ -10,11 +10,10 @@ import gdb
import os
import os.path
import re
-import sys
import struct
import tempfile
-from dumper import DumperBase, Children, toInteger, TopLevelItem
+from dumper import DumperBase, Children, TopLevelItem
from utils import TypeCode
from gdbtracepoint import *
@@ -119,7 +118,6 @@ ScanStackCommand()
class PlainDumper():
def __init__(self, printer):
self.printer = printer
- self.typeCache = {}
def __call__(self, d, value):
if value.nativeValue is None:
@@ -137,8 +135,6 @@ class PlainDumper():
if isinstance(val, str):
# encode and avoid extra quotes ('"') at beginning and end
d.putValue(d.hexencode(val), 'utf8:1:0')
- elif sys.version_info[0] <= 2 and isinstance(val, unicode):
- d.putValue(val)
elif val is not None: # Assuming LazyString
d.putCharArrayValue(val.address, val.length,
val.type.target().sizeof)
@@ -166,7 +162,7 @@ def importPlainDumpers(args):
gdb.execute('disable pretty-printer .* .*')
except:
# Might occur in non-ASCII directories
- DumperBase.warn('COULD NOT DISABLE PRETTY PRINTERS')
+ theDumper.warn('COULD NOT DISABLE PRETTY PRINTERS')
else:
theDumper.usePlainDumpers = True
theDumper.importPlainDumpers()
@@ -192,15 +188,17 @@ class Dumper(DumperBase):
# These values will be kept between calls to 'fetchVariables'.
self.isGdb = True
- self.typeCache = {}
self.interpreterBreakpointResolvers = []
+ def warn(self, message):
+ print('bridgemessage={msg="%s"},' % message.replace('"', '$').encode('latin1'))
+
def prepare(self, args):
self.output = []
self.setVariableFetchingOptions(args)
def fromFrameValue(self, nativeValue):
- #DumperBase.warn('FROM FRAME VALUE: %s' % nativeValue.address)
+ #self.warn('FROM FRAME VALUE: %s' % nativeValue.address)
val = nativeValue
if self.useDynamicType:
try:
@@ -209,71 +207,43 @@ class Dumper(DumperBase):
pass
return self.fromNativeValue(val)
- def nativeValueType(self, nativeValue):
- return self.fromNativeType(nativeValue.type)
-
def fromNativeValue(self, nativeValue):
- #DumperBase.warn('FROM NATIVE VALUE: %s' % nativeValue)
+ #self.warn('FROM NATIVE VALUE: %s' % nativeValue)
self.check(isinstance(nativeValue, gdb.Value))
nativeType = nativeValue.type
code = nativeType.code
+
+ val = self.Value(self)
+ val.nativeValue = nativeValue
+
if code == gdb.TYPE_CODE_REF:
- targetType = self.fromNativeType(nativeType.target().unqualified())
- val = self.createReferenceValue(toInteger(nativeValue.address), targetType)
- val.nativeValue = nativeValue
- #DumperBase.warn('CREATED REF: %s' % val)
+ target_typeid = self.from_native_type(nativeType.target().unqualified())
+ val.ldata = int(nativeValue.address)
+ if self.useDynamicType: # needed for Gdb13393
+ target_typeid = self.dynamic_typeid_at_address(target_typeid, val.ldata)
+ val.typeid = self.create_reference_typeid(target_typeid)
+ #self.warn('CREATED REF: %s' % val)
return val
+
if code == gdb.TYPE_CODE_PTR:
- try:
- nativeTargetValue = nativeValue.dereference()
- except:
- nativeTargetValue = None
- targetType = self.fromNativeType(nativeType.target().unqualified())
- val = self.createPointerValue(toInteger(nativeValue), targetType)
- # The nativeValue is needed in case of multiple inheritance, see
- # QTCREATORBUG-17823. Using it triggers nativeValueDereferencePointer()
- # later which
- # is surprisingly expensive.
- val.nativeValue = nativeValue
- #DumperBase.warn('CREATED PTR 1: %s' % val)
+ target_typeid = self.from_native_type(nativeType.target().unqualified())
+ val.ldata = int(nativeValue)
+ val.typeid = self.create_pointer_typeid(target_typeid)
+ #self.warn('CREATED PTR 1: %s' % val)
if nativeValue.address is not None:
- val.laddress = toInteger(nativeValue.address)
- #DumperBase.warn('CREATED PTR 2: %s' % val)
+ val.laddress = int(nativeValue.address)
+ #self.warn('CREATED PTR 2: %s' % val)
return val
- if code == gdb.TYPE_CODE_TYPEDEF:
- targetType = nativeType.strip_typedefs().unqualified()
- #DumperBase.warn('TARGET TYPE: %s' % targetType)
- if targetType.code == gdb.TYPE_CODE_ARRAY:
- val = self.Value(self)
- else:
- try:
- # Cast may fail for arrays, for typedefs to __uint128_t with
- # gdb.error: That operation is not available on integers
- # of more than 8 bytes.
- # See test for Bug5799, QTCREATORBUG-18450.
- val = self.fromNativeValue(nativeValue.cast(targetType))
- except:
- val = self.Value(self)
- #DumperBase.warn('CREATED TYPEDEF: %s' % val)
- else:
- val = self.Value(self)
- val.nativeValue = nativeValue
if nativeValue.address is not None:
- val.laddress = toInteger(nativeValue.address)
- else:
- size = nativeType.sizeof
- chars = self.lookupNativeType('unsigned char')
- y = nativeValue.cast(chars.array(0, int(nativeType.sizeof - 1)))
- buf = bytearray(struct.pack('x' * size))
- for i in range(size):
- try:
- buf[i] = int(y[i])
- except:
- pass
- val.ldata = bytes(buf)
+ val.laddress = int(nativeValue.address)
+ elif code == gdb.TYPE_CODE_STRUCT:
+ try:
+ val.ldata = nativeValue.bytes # GDB 15 only
+ except:
+ val.ldata = self.nativeDataFromValueFallback(nativeValue, nativeValue.type.sizeof)
- val._type = self.fromNativeType(nativeType)
+ val.typeid = self.from_native_type(nativeType)
val.lIsInScope = not nativeValue.is_optimized_out
code = nativeType.code
if code == gdb.TYPE_CODE_ENUM:
@@ -283,10 +253,15 @@ class Dumper(DumperBase):
val.ldisplay += ' (%s)' % intval
elif code == gdb.TYPE_CODE_COMPLEX:
val.ldisplay = str(nativeValue)
- elif code in [gdb.TYPE_CODE_BOOL, gdb.TYPE_CODE_INT]:
+ elif code == gdb.TYPE_CODE_BOOL:
+ # FIXME: why?
+ # Using ldata breaks StdVariant test, not setting lvalue breaks the Bitfield[s2] test.
+ val.lvalue = int(nativeValue)
+ val.ldata = None
+ elif code == gdb.TYPE_CODE_INT:
try:
# extract int presentation from native value and remember it
- val.lvalue = int(nativeValue)
+ val.ldata = int(nativeValue)
except:
# GDB only support converting integers of max. 64 bits to Python int as of now
pass
@@ -294,65 +269,81 @@ class Dumper(DumperBase):
# val.type.ltarget = nativeValue[0].type.unqualified()
return val
+ def nativeDataFromValueFallback(self, nativeValue, size):
+ chars = self.lookupNativeType('unsigned char')
+ try:
+ y = nativeValue.cast(chars.array(0, int(size - 1)))
+ buf = bytearray(struct.pack('x' * size))
+ for i in range(size):
+ try:
+ buf[i] = int(y[i])
+ except:
+ pass
+ return bytes(buf)
+ except:
+ self.warn('VALUE EXTRACTION FAILED: VALUE: %s SIZE: %s' % (nativeValue, size))
+ return None
+
def ptrSize(self):
result = gdb.lookup_type('void').pointer().sizeof
self.ptrSize = lambda: result
return result
- def fromNativeType(self, nativeType):
+ def from_native_type(self, nativeType):
self.check(isinstance(nativeType, gdb.Type))
- code = nativeType.code
- #DumperBase.warn('FROM NATIVE TYPE: %s' % nativeType)
+
+ #self.warn('FROM NATIVE TYPE: %s' % nativeType)
nativeType = nativeType.unqualified()
- if code == gdb.TYPE_CODE_PTR:
- #DumperBase.warn('PTR')
- targetType = self.fromNativeType(nativeType.target().unqualified())
- return self.createPointerType(targetType)
+ typeid_str = self.native_type_key(nativeType)
+ known_typeid = self.typeid_from_typekey.get(typeid_str, None)
+ if known_typeid is not None:
+ return known_typeid
- if code == gdb.TYPE_CODE_REF:
- #DumperBase.warn('REF')
- targetType = self.fromNativeType(nativeType.target().unqualified())
- return self.createReferenceType(targetType)
-
- if hasattr(gdb, "TYPE_CODE_RVALUE_REF"):
- if code == gdb.TYPE_CODE_RVALUE_REF:
- #DumperBase.warn('RVALUEREF')
- targetType = self.fromNativeType(nativeType.target())
- return self.createRValueReferenceType(targetType)
-
- if code == gdb.TYPE_CODE_ARRAY:
- #DumperBase.warn('ARRAY')
+ code = nativeType.code
+
+ if code == gdb.TYPE_CODE_PTR:
+ #self.warn('PTR')
+ target_typeid = self.from_native_type(nativeType.target().unqualified())
+ typeid = self.create_pointer_typeid(target_typeid)
+
+ elif code == gdb.TYPE_CODE_REF:
+ #self.warn('REF')
+ target_typeid = self.from_native_type(nativeType.target().unqualified())
+ typeid = self.create_reference_typeid(target_typeid)
+
+ elif code == gdb.TYPE_CODE_RVALUE_REF and hasattr(gdb, "TYPE_CODE_RVALUE_REF"):
+ #self.warn('RVALUEREF')
+ target_typeid = self.from_native_type(nativeType.target())
+ typeid = self.create_rvalue_reference_typeid(target_typeid)
+
+ elif code == gdb.TYPE_CODE_ARRAY:
+ #self.warn('ARRAY')
nativeTargetType = nativeType.target().unqualified()
- targetType = self.fromNativeType(nativeTargetType)
+ target_typeid = self.from_native_type(nativeTargetType)
if nativeType.sizeof == 0:
# QTCREATORBUG-23998, note that nativeType.name == None here,
# whereas str(nativeType) returns sth like 'QObject [5]'
count = self.arrayItemCountFromTypeName(str(nativeType), 1)
else:
count = nativeType.sizeof // nativeTargetType.sizeof
- return self.createArrayType(targetType, count)
+ typeid = self.create_array_typeid(target_typeid, count)
- if code == gdb.TYPE_CODE_TYPEDEF:
- #DumperBase.warn('TYPEDEF')
+ elif code == gdb.TYPE_CODE_TYPEDEF:
+ #self.warn('TYPEDEF')
nativeTargetType = nativeType.unqualified()
while nativeTargetType.code == gdb.TYPE_CODE_TYPEDEF:
nativeTargetType = nativeTargetType.strip_typedefs().unqualified()
- targetType = self.fromNativeType(nativeTargetType)
- return self.createTypedefedType(targetType, str(nativeType),
- self.nativeTypeId(nativeType))
+ target_typeid = self.from_native_type(nativeTargetType)
+ typeid = self.create_typedefed_typeid(target_typeid, str(nativeType), typeid_str)
- if code == gdb.TYPE_CODE_ERROR:
+ elif code == gdb.TYPE_CODE_ERROR:
self.warn('Type error: %s' % nativeType)
- return self.Type(self, '')
-
- typeId = self.nativeTypeId(nativeType)
- res = self.typeData.get(typeId, None)
- if res is None:
- tdata = self.TypeData(self, typeId)
- tdata.name = str(nativeType)
- tdata.lbitsize = nativeType.sizeof * 8
- tdata.code = {
+ typeid = 0 # the invalid id
+
+ else:
+ typeid = self.typeid_for_string(typeid_str)
+ type_code = {
#gdb.TYPE_CODE_TYPEDEF : TypeCode.Typedef, # Handled above.
gdb.TYPE_CODE_METHOD: TypeCode.Function,
gdb.TYPE_CODE_VOID: TypeCode.Void,
@@ -372,38 +363,60 @@ class Dumper(DumperBase):
gdb.TYPE_CODE_COMPLEX: TypeCode.Complex,
gdb.TYPE_CODE_STRING: TypeCode.FortranString,
}[code]
- if tdata.code == TypeCode.Enum:
- tdata.enumDisplay = lambda intval, addr, form: \
+ self.type_name_cache[typeid] = str(nativeType)
+ self.type_size_cache[typeid] = nativeType.sizeof
+ self.type_code_cache[typeid] = type_code
+ self.type_nativetype_cache[typeid] = nativeType
+
+ if type_code == TypeCode.Enum:
+ self.type_enum_display_cache[typeid] = lambda intval, addr, form: \
self.nativeTypeEnumDisplay(nativeType, intval, form)
- if tdata.code == TypeCode.Struct:
- tdata.lalignment = lambda: \
- self.nativeStructAlignment(nativeType)
- tdata.lfields = lambda value: \
- self.listMembers(value, nativeType)
- tdata.templateArguments = lambda: \
- self.listTemplateParameters(nativeType)
- # warn('CREATE TYPE: %s' % typeId)
- #else:
- # warn('REUSE TYPE: %s' % typeId)
- return self.Type(self, typeId)
-
- def listTemplateParameters(self, nativeType):
- targs = []
- pos = 0
- while True:
- try:
- targ = nativeType.template_argument(pos)
- except:
- break
- if isinstance(targ, gdb.Type):
- targs.append(self.fromNativeType(targ.unqualified()))
- elif isinstance(targ, gdb.Value):
- targs.append(self.fromNativeValue(targ).value())
- else:
- raise RuntimeError('UNKNOWN TEMPLATE PARAMETER')
- pos += 1
- targs2 = self.listTemplateParametersManually(str(nativeType))
- return targs if len(targs) >= len(targs2) else targs2
+
+ self.type_nativetype_cache[typeid] = nativeType
+
+# FIXME: Field offset caching (or later extraction?) broken
+# if code == gdb.TYPE_CODE_STRUCT:
+# field_type_name = self.type_name_cache.get(typeid, '')
+# #self.warn("CACHING FIELDS OF %s '%s'" % (typeid, field_type_name))
+# try:
+# fields = nativeType.fields()
+# #self.warn("FOUND FIELDS %s" % fields)
+# except:
+# #self.warn("NO FIELDS IN %s '%s'" % (typeid, field_type_name))
+# fields = []
+# for nativeField in fields:
+# field_name = nativeField.name
+# if field_name.startswith('std::allocator'):
+# continue
+# field_bitpos = nativeField.bitpos
+# field_typeid = self.typeid_for_string(str(nativeType))
+# field_size = nativeField.type.sizeof
+# #self.warn("CACHING '%s' OF %s AT BITPOS %s SIZE %s" %
+# # (field_name, typeid, field_bitpos, field_size))
+# self.type_fields_cache[(typeid, field_name)] = self.Field(
+# name=field_name,
+# typeid=field_typeid,
+# bitpos=field_bitpos,
+# bitsize=field_size * 8
+# )
+# pass
+
+
+ #self.warn("FROM NATIVE TYPE: %s %s %s" % (typeid, id(nativeType), nativeType))
+ self.typeid_from_typekey[str(nativeType)] = typeid
+
+ return typeid
+
+ def nativeTemplateParameter(self, typeid, index, nativeType):
+ try:
+ targ = nativeType.template_argument(index)
+ except:
+ return None
+ if isinstance(targ, gdb.Type):
+ return self.Type(self, self.from_native_type(targ.unqualified()))
+ if isinstance(targ, gdb.Value):
+ return self.fromNativeValue(targ).value()
+ raise RuntimeError('UNKNOWN TEMPLATE PARAMETER')
def nativeTypeEnumDisplay(self, nativeType, intval, form):
try:
@@ -432,7 +445,7 @@ class Dumper(DumperBase):
pass
return form % intval
- def nativeTypeId(self, nativeType):
+ def native_type_key(self, nativeType):
if nativeType and (nativeType.code == gdb.TYPE_CODE_TYPEDEF):
return '%s{%s}' % (nativeType, nativeType.strip_typedefs())
name = str(nativeType)
@@ -444,133 +457,106 @@ class Dumper(DumperBase):
c = 's'
else:
return name
- typeId = c + ''.join(['{%s:%s}' % (f.name, self.nativeTypeId(f.type))
- for f in nativeType.fields()])
- return typeId
-
- def nativeStructAlignment(self, nativeType):
- #DumperBase.warn('NATIVE ALIGN FOR %s' % nativeType.name)
- def handleItem(nativeFieldType, align):
- a = self.fromNativeType(nativeFieldType).alignment()
- return a if a > align else align
- align = 1
- for f in nativeType.fields():
- align = handleItem(f.type, align)
- return align
-
- #except:
- # # Happens in the BoostList dumper for a 'const bool'
- # # item named 'constant_time_size'. There isn't anything we can do
- # # in this case.
- # pass
+ id_str = c + ''.join(['{%s:%s}' %
+ (f.name, self.typeid_for_string(self.native_type_key(f.type)))
+ for f in nativeType.fields()])
+ #self.warn("NATIVE TYPE KEY: %s" % id_str)
+ return id_str
- #yield value.extractField(field)
-
- def memberFromNativeFieldAndValue(self, nativeField, nativeValue, fieldName, value):
- nativeMember = self.nativeMemberFromField(nativeValue, nativeField)
- if nativeMember is None:
- val = self.Value(self)
- val.name = fieldName
- val._type = self.fromNativeType(nativeField.type)
- val.lIsInScope = False
- return val
- val = self.fromNativeValue(nativeMember)
- nativeFieldType = nativeField.type.unqualified()
- if nativeField.bitsize:
- val.lvalue = int(nativeMember)
- val.laddress = None
- fieldType = self.fromNativeType(nativeFieldType)
- val._type = self.createBitfieldType(fieldType, nativeField.bitsize)
- val.isBaseClass = nativeField.is_base_class
- val.name = fieldName
- return val
-
- def nativeMemberFromField(self, nativeValue, nativeField):
- if nativeField.is_base_class:
- return nativeValue.cast(nativeField.type)
- try:
- return nativeValue[nativeField]
- except:
- pass
- try:
- return nativeValue[nativeField.name]
- except:
- pass
- return None
-
- def listMembers(self, value, nativeType):
+ def nativeListMembers(self, value, nativeType, include_base):
nativeValue = value.nativeValue
+ value_size = self.type_size(value.typeid)
+ ldata = bytes(self.value_data(value, value_size))
+ laddress = value.laddress
anonNumber = 0
- #DumperBase.warn('LISTING FIELDS FOR %s' % nativeType)
+ fields = []
+ #self.warn('LISTING FIELDS FOR %s' % nativeType)
for nativeField in nativeType.fields():
- fieldName = nativeField.name
+ if not include_base and nativeField.is_base_class:
+ continue
+
+ field_name = nativeField.name
# Something without a name.
# Anonymous union? We need a dummy name to distinguish
# multiple anonymous unions in the struct.
# Since GDB commit b5b08fb4 anonymous structs get also reported
# with a 'None' name.
- if fieldName is None or len(fieldName) == 0:
- # Something without a name.
- # Anonymous union? We need a dummy name to distinguish
- # multiple anonymous unions in the struct.
+ if field_name is None or len(field_name) == 0:
anonNumber += 1
- fieldName = '#%s' % anonNumber
- #DumperBase.warn('FIELD: %s' % fieldName)
+ field_name = '#%s' % anonNumber
+ #self.warn('FIELD: %s' % field_name)
+
+ nativeFieldType = nativeField.type.unqualified()
+ field_typeid = self.from_native_type(nativeFieldType)
+ #self.warn(' TYPE: %s' % nativeFieldType)
+ #self.warn(' TYPE KEY: %s' % self.native_type_key(nativeFieldType))
+
+ if nativeValue is not None:
+ try:
+ native_member = nativeValue[nativeField]
+ except:
+ self.warn(' COULD NOT ACCESS FIELD: %s' % nativeFieldType)
+ continue
+
+ val = self.fromNativeValue(native_member)
+ if nativeField.bitsize:
+ val.lvalue = None
+ val.ldata = int(native_member)
+ val.laddress = None
+ val.typeid = self.create_bitfield_typeid(field_typeid, nativeField.bitsize)
+ val.isBaseClass = nativeField.is_base_class
+ val.name = field_name
+ fields.append(val)
+ continue
+
# hasattr(nativeField, 'bitpos') == False indicates a static field,
- # but if we have access to a nativeValue .fromNativeField will
+ # but if we have access to a nativeValue, so fromNativeField will
# also succeed. We essentially skip only static members from
# artificial values, like array members constructed from address.
- if hasattr(nativeField, 'bitpos') or nativeValue is not None:
- yield self.fromNativeField(nativeField, nativeValue, fieldName)
+ if not hasattr(nativeField, 'bitpos'):
+ continue
- def fromNativeField(self, nativeField, nativeValue, fieldName):
- nativeFieldType = nativeField.type.unqualified()
- #DumperBase.warn(' TYPE: %s' % nativeFieldType)
- #DumperBase.warn(' TYPEID: %s' % self.nativeTypeId(nativeFieldType))
-
- if hasattr(nativeField, 'bitpos'):
bitpos = nativeField.bitpos
- else:
- bitpos = 0
- if hasattr(nativeField, 'bitsize') and nativeField.bitsize != 0:
- bitsize = nativeField.bitsize
- else:
- bitsize = 8 * nativeFieldType.sizeof
+ if hasattr(nativeField, 'bitsize') and nativeField.bitsize != 0:
+ bitsize = nativeField.bitsize
+ else:
+ bitsize = 8 * nativeFieldType.sizeof
- fieldType = self.fromNativeType(nativeFieldType)
- if bitsize != nativeFieldType.sizeof * 8:
- fieldType = self.createBitfieldType(fieldType, bitsize)
- else:
- fieldType = fieldType
+ field_typeid = self.from_native_type(nativeFieldType)
+ is_bitfield = bitsize != nativeFieldType.sizeof * 8
+
+ val = self.Value(self)
+ val.name = field_name
+ val.isBaseClass = nativeField.is_base_class
+
+ if is_bitfield:
+ val.typeid = self.create_bitfield_typeid(field_typeid, bitsize)
+ val.ldata = self.value_extract_bits(value, bitpos, bitsize)
+ else:
+ val.typeid = field_typeid
+ field_offset = bitpos // 8
+ if laddress is not None:
+ val.laddress = laddress + field_offset
+ field_size = (bitsize + 7) // 8
+ val.ldata = ldata[field_offset:field_offset + field_size]
+
+ #self.warn('GOT VAL %s FOR FIELD %s' % (val, nativeField))
+ fields.append(val)
+
+ return fields
- if nativeValue is None:
- extractor = None
- else:
- extractor = lambda value, \
- capturedNativeField = nativeField, \
- capturedNativeValue = nativeValue, \
- capturedFieldName = fieldName: \
- self.memberFromNativeFieldAndValue(capturedNativeField,
- capturedNativeValue,
- capturedFieldName,
- value)
-
- #DumperBase.warn("FOUND NATIVE FIELD: %s bitpos: %s" % (fieldName, bitpos))
- return self.Field(dumper=self, name=fieldName, isBase=nativeField.is_base_class,
- bitsize=bitsize, bitpos=bitpos, type=fieldType,
- extractor=extractor)
def listLocals(self, partialVar):
frame = gdb.selected_frame()
try:
block = frame.block()
- #DumperBase.warn('BLOCK: %s ' % block)
+ #self.warn('BLOCK: %s ' % block)
except RuntimeError as error:
- #DumperBase.warn('BLOCK IN FRAME NOT ACCESSIBLE: %s' % error)
+ #self.warn('BLOCK IN FRAME NOT ACCESSIBLE: %s' % error)
return []
except:
self.warn('BLOCK NOT ACCESSIBLE FOR UNKNOWN REASONS')
@@ -594,14 +580,12 @@ class Dumper(DumperBase):
if partialVar is not None and partialVar != name:
continue
- # 'NotImplementedError: Symbol type not yet supported in
- # Python scripts.'
- #DumperBase.warn('SYMBOL %s (%s, %s)): ' % (symbol, name, symbol.name))
+ #self.warn('SYMBOL %s (%s, %s)): ' % (symbol, name, symbol.name))
if self.passExceptions and not self.isTesting:
nativeValue = frame.read_var(name, block)
value = self.fromFrameValue(nativeValue)
value.name = name
- #DumperBase.warn('READ 0: %s' % value.stringify())
+ #self.warn('READ 0: %s' % value.stringify())
items.append(value)
continue
@@ -610,14 +594,14 @@ class Dumper(DumperBase):
nativeValue = frame.read_var(name, block)
value = self.fromFrameValue(nativeValue)
value.name = name
- #DumperBase.warn('READ 1: %s' % value.stringify())
+ #self.warn('READ 1: %s' % value.stringify())
items.append(value)
continue
except:
pass
try:
- #DumperBase.warn('READ 2: %s' % item.value)
+ #self.warn('READ 2: %s' % item.value)
value = self.fromFrameValue(frame.read_var(name))
value.name = name
items.append(value)
@@ -631,8 +615,8 @@ class Dumper(DumperBase):
pass
try:
- #DumperBase.warn('READ 3: %s %s' % (name, item.value))
- #DumperBase.warn('ITEM 3: %s' % item.value)
+ #self.warn('READ 3: %s %s' % (name, item.value))
+ #self.warn('ITEM 3: %s' % item.value)
value = self.fromFrameValue(gdb.parse_and_eval(name))
value.name = name
items.append(value)
@@ -661,16 +645,17 @@ class Dumper(DumperBase):
return self.ptrSize() == 8
def fetchVariables(self, args):
+ start_time = time.perf_counter()
self.resetStats()
self.prepare(args)
self.isBigEndian = gdb.execute('show endian', to_string=True).find('big endian') > 0
self.packCode = '>' if self.isBigEndian else '<'
- (ok, res) = self.tryFetchInterpreterVariables(args)
- if ok:
- safePrint(res)
- return
+ #(ok, res) = self.tryFetchInterpreterVariables(args)
+ #if ok:
+ # safePrint(res)
+ # return
self.put('data=[')
@@ -679,7 +664,7 @@ class Dumper(DumperBase):
partialName = partialVar.split('.')[1].split('@')[0] if isPartial else None
variables = self.listLocals(partialName)
- #DumperBase.warn('VARIABLES: %s' % variables)
+ #self.warn('VARIABLES: %s' % variables)
# Take care of the return value of the last function call.
if len(self.resultVarName) > 0:
@@ -711,9 +696,12 @@ class Dumper(DumperBase):
self.put(',qtnamespace="%s"' % self.qtNamespaceToReport)
self.qtNamespaceToReport = None
+ run_time = time.perf_counter() - start_time
+ #self.warn("PTIME: %s" % run_time)
self.put(',partial="%d"' % isPartial)
+ self.put(',runtime="%s"' % run_time)
self.put(',counts=%s' % self.counts)
- self.put(',timings=%s' % self.timings)
+ #self.put(',timings=%s' % self.timings)
self.reportResult(''.join(self.output), args)
def parseAndEvaluate(self, exp):
@@ -721,7 +709,7 @@ class Dumper(DumperBase):
return None if val is None else self.fromNativeValue(val)
def nativeParseAndEvaluate(self, exp):
- #DumperBase.warn('EVALUATE "%s"' % exp)
+ #self.warn('EVALUATE "%s"' % exp)
try:
val = gdb.parse_and_eval(exp)
return val
@@ -744,20 +732,20 @@ class Dumper(DumperBase):
else:
arg += a
- #DumperBase.warn('CALL: %s -> %s(%s)' % (value, function, arg))
- typeName = value.type.name
- if typeName.find(':') >= 0:
- typeName = "'" + typeName + "'"
+ #self.warn('CALL: %s -> %s(%s)' % (value, function, arg))
+ type_name = value.type.name
+ if type_name.find(':') >= 0:
+ type_name = "'" + type_name + "'"
# 'class' is needed, see http://sourceware.org/bugzilla/show_bug.cgi?id=11912
- #exp = '((class %s*)%s)->%s(%s)' % (typeName, value.laddress, function, arg)
+ #exp = '((class %s*)%s)->%s(%s)' % (type_name, value.laddress, function, arg)
addr = value.address()
if addr is None:
addr = self.pokeValue(value)
- #DumperBase.warn('PTR: %s -> %s(%s)' % (value, function, addr))
- exp = '((%s*)0x%x)->%s(%s)' % (typeName, addr, function, arg)
- #DumperBase.warn('CALL: %s' % exp)
+ #self.warn('PTR: %s -> %s(%s)' % (value, function, addr))
+ exp = '((%s*)0x%x)->%s(%s)' % (type_name, addr, function, arg)
+ #self.warn('CALL: %s' % exp)
result = gdb.parse_and_eval(exp)
- #DumperBase.warn(' -> %s' % result)
+ #self.warn(' -> %s' % result)
res = self.fromNativeValue(result)
if value.address() is None:
self.releaseValue(addr)
@@ -765,9 +753,9 @@ class Dumper(DumperBase):
def makeExpression(self, value):
typename = '::' + value.type.name
- #DumperBase.warn(' TYPE: %s' % typename)
+ #self.warn(' TYPE: %s' % typename)
exp = '(*(%s*)(0x%x))' % (typename, value.address())
- #DumperBase.warn(' EXP: %s' % exp)
+ #self.warn(' EXP: %s' % exp)
return exp
def makeStdString(init):
@@ -785,14 +773,14 @@ class Dumper(DumperBase):
size = value.type.size()
data = value.data()
h = self.hexencode(data)
- #DumperBase.warn('DATA: %s' % h)
+ #self.warn('DATA: %s' % h)
string = ''.join('\\x' + h[2 * i:2 * i + 2] for i in range(size))
exp = '(%s*)memcpy(calloc(1, %d), "%s", %d)' \
% (value.type.name, size, string, size)
- #DumperBase.warn('EXP: %s' % exp)
+ #self.warn('EXP: %s' % exp)
res = gdb.parse_and_eval(exp)
- #DumperBase.warn('RES: %s' % res)
- return toInteger(res)
+ #self.warn('RES: %s' % res)
+ return int(res)
def releaseValue(self, address):
gdb.parse_and_eval('free(0x%x)' % address)
@@ -819,7 +807,7 @@ class Dumper(DumperBase):
return self.cachedInferior
def readRawMemory(self, address, size):
- #DumperBase.warn('READ: %s FROM 0x%x' % (size, address))
+ #self.warn('READ: %s FROM 0x%x' % (size, address))
if address == 0 or size == 0:
return bytes()
res = self.selectedInferior().read_memory(address, size)
@@ -832,7 +820,7 @@ class Dumper(DumperBase):
return 0
try:
# Older GDB ~7.4 don't have gdb.Symbol.value()
- return toInteger(symbol.value().address)
+ return int(symbol.value().address)
except:
pass
@@ -1020,7 +1008,7 @@ class Dumper(DumperBase):
def findSymbol(self, symbolName):
try:
- return toInteger(gdb.parse_and_eval("(size_t)&'%s'" % symbolName))
+ return int(gdb.parse_and_eval("(size_t)&'%s'" % symbolName))
except:
return 0
@@ -1052,30 +1040,24 @@ class Dumper(DumperBase):
def handleQtCoreLoaded(self, objfile):
fd, tmppath = tempfile.mkstemp()
os.close(fd)
- try:
- cmd = 'maint print msymbols -objfile "%s" -- %s' % (objfile.filename, tmppath)
- symbols = gdb.execute(cmd, to_string=True)
- except:
- try:
- # command syntax depends on gdb version - below is gdb < 8
- cmd = 'maint print msymbols %s "%s"' % (tmppath, objfile.filename)
- symbols = gdb.execute(cmd, to_string=True)
- except:
- pass
+ cmd = 'maint print msymbols -objfile "%s" -- %s' % (objfile.filename, tmppath)
+ symbols = gdb.execute(cmd, to_string=True)
ns = ''
with open(tmppath) as f:
+ ns1re = re.compile(r'_ZN?(\d*)(\w*)L17msgHandlerGrabbedE? ')
+ ns2re = re.compile(r'_ZN?(\d*)(\w*)L17currentThreadDataE? ')
for line in f:
- if line.find('msgHandlerGrabbed ') >= 0:
+ if 'msgHandlerGrabbed ' in line:
# [11] b 0x7ffff683c000 _ZN4MynsL17msgHandlerGrabbedE
# section .tbss Myns::msgHandlerGrabbed qlogging.cpp
- ns = re.split(r'_ZN?(\d*)(\w*)L17msgHandlerGrabbedE? ', line)[2]
+ ns = ns1re.split(line)[2]
if len(ns):
ns += '::'
break
- if line.find('currentThreadData ') >= 0:
+ if 'currentThreadData ' in line:
# [ 0] b 0x7ffff67d3000 _ZN2UUL17currentThreadDataE
# section .tbss UU::currentThreadData qthread_unix.cpp\\n
- ns = re.split(r'_ZN?(\d*)(\w*)L17currentThreadDataE? ', line)[2]
+ ns = ns2re.split(line)[2]
if len(ns):
ns += '::'
break
@@ -1104,21 +1086,21 @@ class Dumper(DumperBase):
self.qtPropertyFunc = self.findSymbol(sym)
def assignValue(self, args):
- typeName = self.hexdecode(args['type'])
+ type_name = self.hexdecode(args['type'])
expr = self.hexdecode(args['expr'])
value = self.hexdecode(args['value'])
simpleType = int(args['simpleType'])
ns = self.qtNamespace()
- if typeName.startswith(ns):
- typeName = typeName[len(ns):]
- typeName = typeName.replace('::', '__')
- pos = typeName.find('<')
+ if type_name.startswith(ns):
+ type_name = type_name[len(ns):]
+ type_name = type_name.replace('::', '__')
+ pos = type_name.find('<')
if pos != -1:
- typeName = typeName[0:pos]
- if typeName in self.qqEditable and not simpleType:
- #self.qqEditable[typeName](self, expr, value)
+ type_name = type_name[0:pos]
+ if type_name in self.qqEditable and not simpleType:
+ #self.qqEditable[type_name](self, expr, value)
expr = self.parseAndEvaluate(expr)
- self.qqEditable[typeName](self, expr, value)
+ self.qqEditable[type_name](self, expr, value)
else:
cmd = 'set variable (%s)=%s' % (expr, value)
gdb.execute(cmd)
@@ -1152,63 +1134,28 @@ class Dumper(DumperBase):
nativeValue = value.nativeValue
return self.fromNativeValue(nativeValue.cast(nativeValue.type.target()))
- def nativeDynamicTypeName(self, address, baseType):
- # Needed for Gdb13393 test.
- nativeType = self.lookupNativeType(baseType.name)
- if nativeType is None:
- return None
- nativeTypePointer = nativeType.pointer()
- nativeValue = gdb.Value(address).cast(nativeTypePointer).dereference()
- val = nativeValue.cast(nativeValue.dynamic_type)
- return str(val.type)
- #try:
- # vtbl = gdb.execute('info symbol {%s*}0x%x' % (baseType.name, address), to_string = True)
- #except:
- # return None
- #pos1 = vtbl.find('vtable ')
- #if pos1 == -1:
- # return None
- #pos1 += 11
- #pos2 = vtbl.find(' +', pos1)
- #if pos2 == -1:
- # return None
- #return vtbl[pos1 : pos2]
-
- def nativeDynamicType(self, address, baseType):
+ def nativeDynamicType(self, address, base_typeid):
# Needed for Gdb13393 test.
- nativeType = self.lookupNativeType(baseType.name)
+ nativeType = self.type_nativetype_cache.get(base_typeid, None)
if nativeType is None:
- return baseType
+ return base_typeid
nativeTypePointer = nativeType.pointer()
nativeValue = gdb.Value(address).cast(nativeTypePointer).dereference()
- return self.fromNativeType(nativeValue.dynamic_type)
+ return self.from_native_type(nativeValue.dynamic_type)
def enumExpression(self, enumType, enumValue):
return self.qtNamespace() + 'Qt::' + enumValue
- def lookupNativeType(self, typeName):
- nativeType = self.lookupNativeTypeHelper(typeName)
- if nativeType is not None:
- self.check(isinstance(nativeType, gdb.Type))
- return nativeType
-
- def lookupNativeTypeHelper(self, typeName):
- typeobj = self.typeCache.get(typeName)
- #DumperBase.warn('LOOKUP 1: %s -> %s' % (typeName, typeobj))
- if typeobj is not None:
- return typeobj
-
- if typeName == 'void':
- typeobj = gdb.lookup_type(typeName)
- self.typeCache[typeName] = typeobj
- self.typesToReport[typeName] = typeobj
+ def lookupNativeType(self, type_name):
+ if type_name == 'void':
+ typeobj = gdb.lookup_type(type_name)
+ self.typesToReport[type_name] = typeobj
return typeobj
#try:
- # typeobj = gdb.parse_and_eval('{%s}&main' % typeName).typeobj
+ # typeobj = gdb.parse_and_eval('{%s}&main' % type_name).typeobj
# if not typeobj is None:
- # self.typeCache[typeName] = typeobj
- # self.typesToReport[typeName] = typeobj
+ # self.typesToReport[type_name] = typeobj
# return typeobj
#except:
# pass
@@ -1217,22 +1164,21 @@ class Dumper(DumperBase):
# gcc produces '{anonymous}', gdb '(anonymous namespace)'
# '<unnamed>' has been seen too. The only thing gdb
# understands when reading things back is '(anonymous namespace)'
- if typeName.find('{anonymous}') != -1:
- ts = typeName
+ if type_name.find('{anonymous}') != -1:
+ ts = type_name
ts = ts.replace('{anonymous}', '(anonymous namespace)')
typeobj = self.lookupNativeType(ts)
if typeobj is not None:
- self.typeCache[typeName] = typeobj
- self.typesToReport[typeName] = typeobj
+ self.typesToReport[type_name] = typeobj
return typeobj
- #DumperBase.warn(" RESULT FOR 7.2: '%s': %s" % (typeName, typeobj))
+ #self.warn(" RESULT FOR 7.2: '%s': %s" % (type_name, typeobj))
# This part should only trigger for
# gdb 7.1 for types with namespace separators.
# And anonymous namespaces.
- ts = typeName
+ ts = type_name
while True:
if ts.startswith('class '):
ts = ts[6:]
@@ -1259,36 +1205,32 @@ class Dumper(DumperBase):
typeobj = self.lookupNativeType(ts[0:-1])
if typeobj is not None:
typeobj = typeobj.pointer()
- self.typeCache[typeName] = typeobj
- self.typesToReport[typeName] = typeobj
+ self.typesToReport[type_name] = typeobj
return typeobj
try:
- #DumperBase.warn("LOOKING UP 1 '%s'" % ts)
+ #self.warn("LOOKING UP 1 '%s'" % ts)
typeobj = gdb.lookup_type(ts)
except RuntimeError as error:
- #DumperBase.warn("LOOKING UP 2 '%s' ERROR %s" % (ts, error))
+ #self.warn("LOOKING UP '%s' FAILED" % ts)
+ pass
+ #self.warn("LOOKING UP 2 '%s' ERROR %s" % (ts, error))
# See http://sourceware.org/bugzilla/show_bug.cgi?id=11912
exp = "(class '%s'*)0" % ts
try:
typeobj = self.parse_and_eval(exp).type.target()
- #DumperBase.warn("LOOKING UP 3 '%s'" % typeobj)
+ #self.warn("LOOKING UP 3 '%s'" % typeobj)
except:
# Can throw 'RuntimeError: No type named class Foo.'
pass
- except:
- #DumperBase.warn("LOOKING UP '%s' FAILED" % ts)
- pass
if typeobj is not None:
- #DumperBase.warn('CACHING: %s' % typeobj)
- self.typeCache[typeName] = typeobj
- self.typesToReport[typeName] = typeobj
+ #self.warn('CACHING: %s' % typeobj)
+ self.typesToReport[type_name] = typeobj
# This could still be None as gdb.lookup_type('char[3]') generates
# 'RuntimeError: No type named char[3]'
- #self.typeCache[typeName] = typeobj
- #self.typesToReport[typeName] = typeobj
+ #self.typesToReport[type_name] = typeobj
return typeobj
def doContinue(self):
@@ -1332,7 +1274,7 @@ class Dumper(DumperBase):
if typeobj.code == gdb.TYPE_CODE_PTR:
dereftype = typeobj.target().unqualified()
if dereftype.name == needle:
- addr = toInteger(value)
+ addr = int(value)
res = None
for pat in pats:
try:
@@ -1442,14 +1384,6 @@ class Dumper(DumperBase):
def reportResult(self, result, args):
print('result={token="%s",%s}' % (args.get("token", 0), result))
- def profile1(self, args):
- '''Internal profiling'''
- import cProfile
- tempDir = tempfile.gettempdir() + '/bbprof'
- cProfile.run('theDumper.fetchVariables(%s)' % args, tempDir)
- import pstats
- pstats.Stats(tempDir).sort_stats('time').print_stats()
-
def profile2(self, args):
import timeit
print(timeit.repeat('theDumper.fetchVariables(%s)' % args,
diff --git a/share/qtcreator/debugger/lldbbridge.py b/share/qtcreator/debugger/lldbbridge.py
index b64d115a0a..6b08ac3d32 100644
--- a/share/qtcreator/debugger/lldbbridge.py
+++ b/share/qtcreator/debugger/lldbbridge.py
@@ -116,33 +116,29 @@ class Dumper(DumperBase):
self.isInterrupting_ = False
self.interpreterBreakpointResolvers = []
- DumperBase.warn = Dumper.warn_impl
self.report('lldbversion=\"%s\"' % lldb.SBDebugger.GetVersionString())
- @staticmethod
- def warn_impl(message):
- if message[-1:] == '\n':
- message += '\n'
+ def warn(self, msg):
+ #self.put('{name="%s",value="",type="",numchild="0"},' % toCString(msg))
+ if msg[-1:] == '\n':
+ msg += '\n'
print('@\nbridgemessage={msg="%s",channel="%s"}\n@'
- % (message.replace('"', '$'), LogChannel.AppError))
-
- def fromNativeFrameValue(self, nativeValue):
- return self.fromNativeValue(nativeValue)
+ % (msg.replace('"', '$'), LogChannel.AppError))
def fromNativeValue(self, nativeValue):
self.check(isinstance(nativeValue, lldb.SBValue))
nativeType = nativeValue.GetType()
- typeName = nativeType.GetName()
+ type_name = nativeType.GetName()
code = nativeType.GetTypeClass()
# Display the result of GetSummary() for Core Foundation string
# and string-like types.
summary = None
if self.useFancy:
- if (typeName.startswith('CF')
- or typeName.startswith('__CF')
- or typeName.startswith('NS')
- or typeName.startswith('__NSCF')):
+ if (type_name.startswith('CF')
+ or type_name.startswith('__CF')
+ or type_name.startswith('NS')
+ or type_name.startswith('__NSCF')):
if code == lldb.eTypeClassPointer:
summary = nativeValue.Dereference().GetSummary()
elif code == lldb.eTypeClassReference:
@@ -156,26 +152,26 @@ class Dumper(DumperBase):
nativeTargetType = nativeType.GetDereferencedType()
if not nativeTargetType.IsPointerType():
nativeTargetType = nativeTargetType.GetUnqualifiedType()
- targetType = self.fromNativeType(nativeTargetType)
- val = self.createReferenceValue(nativeValue.GetValueAsUnsigned(), targetType)
+ target_typeid = self.from_native_type(nativeTargetType)
+ target_address = nativeValue.GetValueAsUnsigned()
+ val = self.Value(self)
+ val.ldata = target_address.to_bytes(self.ptrSize(), 'little')
+ if self.useDynamicType:
+ target_typeid = self.dynamic_typeid_at_address(target_typeid, target_address)
+ val.typeid = self.create_reference_typeid(target_typeid)
val.laddress = nativeValue.AddressOf().GetValueAsUnsigned()
- #DumperBase.warn('CREATED REF: %s' % val)
+ #self.warn('CREATED REF: %s' % val)
+
elif code == lldb.eTypeClassPointer:
nativeTargetType = nativeType.GetPointeeType()
if not nativeTargetType.IsPointerType():
nativeTargetType = nativeTargetType.GetUnqualifiedType()
- targetType = self.fromNativeType(nativeTargetType)
- val = self.createPointerValue(nativeValue.GetValueAsUnsigned(), targetType)
- #DumperBase.warn('CREATED PTR 1: %s' % val)
+ target_typeid = self.from_native_type(nativeTargetType)
+ val = self.Value(self)
+ val.ldata = nativeValue.GetValueAsUnsigned()
+ val.typeid = self.create_pointer_typeid(target_typeid)
val.laddress = nativeValue.AddressOf().GetValueAsUnsigned()
- #DumperBase.warn('CREATED PTR 2: %s' % val)
- elif code == lldb.eTypeClassTypedef:
- nativeTargetType = nativeType.GetUnqualifiedType()
- if hasattr(nativeTargetType, 'GetCanonicalType'):
- nativeTargetType = nativeTargetType.GetCanonicalType()
- val = self.fromNativeValue(nativeValue.Cast(nativeTargetType))
- val._type = self.fromNativeType(nativeType)
- #DumperBase.warn('CREATED TYPEDEF: %s' % val)
+
else:
val = self.Value(self)
address = nativeValue.GetLoadAddress()
@@ -193,7 +189,7 @@ class Dumper(DumperBase):
except:
pass
- val._type = self.fromNativeType(nativeType)
+ val.typeid = self.from_native_type(nativeType)
if code == lldb.eTypeClassEnumeration:
intval = nativeValue.GetValueAsSigned()
@@ -209,43 +205,32 @@ class Dumper(DumperBase):
val.ldisplay = str(nativeValue.GetValue())
#elif code == lldb.eTypeClassArray:
# if hasattr(nativeType, 'GetArrayElementType'): # New in 3.8(?) / 350.x
- # val.type.ltarget = self.fromNativeType(nativeType.GetArrayElementType())
+ # val.type.ltarget = self.from_native_type(nativeType.GetArrayElementType())
# else:
# fields = nativeType.get_fields_array()
# if len(fields):
- # val.type.ltarget = self.fromNativeType(fields[0])
+ # val.type.ltarget = self.from_native_type(fields[0])
#elif code == lldb.eTypeClassVector:
- # val.type.ltarget = self.fromNativeType(nativeType.GetVectorElementType())
+ # val.type.ltarget = self.from_native_type(nativeType.GetVectorElementType())
val.summary = summary
val.lIsInScope = nativeValue.IsInScope()
val.name = nativeValue.GetName()
return val
- def nativeStructAlignment(self, nativeType):
- def handleItem(nativeFieldType, align):
- a = self.fromNativeType(nativeFieldType).alignment()
- return a if a > align else align
- align = 1
- for i in range(nativeType.GetNumberOfDirectBaseClasses()):
- base = nativeType.GetDirectBaseClassAtIndex(i)
- align = handleItem(base.GetType(), align)
- for i in range(nativeType.GetNumberOfFields()):
- child = nativeType.GetFieldAtIndex(i)
- align = handleItem(child.GetType(), align)
- return align
-
- def listMembers(self, value, nativeType):
- #DumperBase.warn("ADDR: 0x%x" % self.fakeAddress_)
- if value.laddress:
- fakeAddress = lldb.SBAddress(value.laddress, self.target)
- fakeLAddress = value.laddress
- else:
- fakeAddress = self.fakeAddress_
- fakeLAddress = self.fakeLAddress_
+ def nativeListMembers(self, value, nativeType, include_base):
+ #self.warn("ADDR: 0x%x" % self.fakeAddress_)
+ nativeValue = value.nativeValue
+ if nativeValue is None:
+ if value.laddress:
+ fakeAddress = lldb.SBAddress(value.laddress, self.target)
+ fakeLAddress = value.laddress
+ else:
+ fakeAddress = self.fakeAddress_
+ fakeLAddress = self.fakeLAddress_
+ nativeValue = self.target.CreateValueFromAddress('x', fakeAddress, nativeType)
- fakeValue = self.target.CreateValueFromAddress('x', fakeAddress, nativeType)
- fakeValue.SetPreferSyntheticValue(False)
+ nativeValue.SetPreferSyntheticValue(False)
baseNames = {}
for i in range(nativeType.GetNumberOfDirectBaseClasses()):
@@ -262,86 +247,99 @@ class Dumper(DumperBase):
# Normal members and non-empty base classes.
anonNumber = 0
- for i in range(fakeValue.GetNumChildren()):
- nativeField = fakeValue.GetChildAtIndex(i)
+
+ fields = []
+ for i in range(nativeValue.GetNumChildren()):
+ nativeField = nativeValue.GetChildAtIndex(i)
nativeField.SetPreferSyntheticValue(False)
fieldName = nativeField.GetName()
nativeFieldType = nativeField.GetType()
if fieldName in fieldBits:
- (fieldBitsize, fieldBitpos, isBitfield) = fieldBits[fieldName]
+ (bitsize, bitpos, isBitfield) = fieldBits[fieldName]
else:
- fieldBitsize = nativeFieldType.GetByteSize() * 8
- fieldBitpos = None
+ bitsize = nativeFieldType.GetByteSize() * 8
+ bitpos = None
isBitfield = False
if isBitfield: # Bit fields
- fieldType = self.createBitfieldType(
- self.createType(self.typeName(nativeFieldType)), fieldBitsize)
- yield self.Field(self, name=fieldName, type=fieldType,
- bitsize=fieldBitsize, bitpos=fieldBitpos)
+ field_typeid = self.create_bitfield_typeid(
+ self.create_typeid(nativeFieldType.GetName()), bitsize)
+ val = self.Value(self)
+ val.name = fieldName
+ val.isBaseClass = False
+ val.typeid = field_typeid
+ val.ldata = self.value_extract_bits(value, bitpos, bitsize)
+ val.laddress = None
+ fields.append(val)
elif fieldName is None: # Anon members
anonNumber += 1
fieldName = '#%s' % anonNumber
- fakeMember = fakeValue.GetChildAtIndex(i)
+ fakeMember = nativeValue.GetChildAtIndex(i)
fakeMemberAddress = fakeMember.GetLoadAddress()
- offset = fakeMemberAddress - fakeLAddress
- yield self.Field(self, name=fieldName, type=self.fromNativeType(nativeFieldType),
- bitsize=fieldBitsize, bitpos=8 * offset)
+ val = self.Value(self)
+ val.name = fieldName
+ val.isBaseClass = False
+ val.typeid = typeid=self.from_native_type(nativeFieldType)
+ field_offset = fakeMemberAddress - fakeLAddress
+ if value.laddress is not None:
+ val.laddress = value.laddress + field_offset
+ if value.ldata is not None:
+ field_size = (bitsize + 7) // 8
+ val.ldata = value.ldata[field_offset:field_offset + field_size]
+ fields.append(val)
elif fieldName in baseNames: # Simple bases
- member = self.fromNativeValue(fakeValue.GetChildAtIndex(i))
+ member = self.fromNativeValue(nativeValue.GetChildAtIndex(i))
member.isBaseClass = True
- yield member
+ fields.append(member)
else: # Normal named members
- member = self.fromNativeValue(fakeValue.GetChildAtIndex(i))
+ member = self.fromNativeValue(nativeValue.GetChildAtIndex(i))
member.name = nativeField.GetName()
- yield member
-
- # Empty bases are not covered above.
- for i in range(nativeType.GetNumberOfDirectBaseClasses()):
- fieldObj = nativeType.GetDirectBaseClassAtIndex(i)
- fieldType = fieldObj.GetType()
- if fieldType.GetNumberOfFields() == 0:
- if fieldType.GetNumberOfDirectBaseClasses() == 0:
- member = self.Value(self)
- fieldName = fieldObj.GetName()
- member._type = self.fromNativeType(fieldType)
- member.name = fieldName
- member.fields = []
- if False:
- # This would be correct if we came here only for
- # truly empty base classes. Alas, we don't, see below.
- member.ldata = bytes()
- member.lbitsize = fieldType.GetByteSize() * 8
- else:
- # This is a hack. LLDB 3.8 reports declared but not defined
- # types as having no fields and(!) size == 1. At least
- # for the common case of a single base class we can
- # fake the contents by using the whole derived object's
- # data as base class data.
- data = fakeValue.GetData()
- size = nativeType.GetByteSize()
- member.lbitsize = size * 8
- error = lldb.SBError()
- member.laddress = value.laddress
- member.ldata = data.ReadRawData(error, 0, size)
- member.isBaseClass = True
- member.ltype = self.fromNativeType(fieldType)
- member.name = fieldName
- yield member
+ fields.append(member)
+
+
+ if include_base:
+ # Empty bases are not covered above.
+ for i in range(nativeType.GetNumberOfDirectBaseClasses()):
+ fieldObj = nativeType.GetDirectBaseClassAtIndex(i)
+ fieldType = fieldObj.GetType()
+ if fieldType.GetNumberOfFields() == 0:
+ if fieldType.GetNumberOfDirectBaseClasses() == 0:
+ member = self.Value(self)
+ fieldName = fieldObj.GetName()
+ member.typeid = self.from_native_type(fieldType)
+ member.name = fieldName
+ member.fields = []
+ if False:
+ # This would be correct if we came here only for
+ # truly empty base classes. Alas, we don't, see below.
+ member.ldata = bytes()
+ else:
+ # This is a hack. LLDB 3.8 reports declared but not defined
+ # types as having no fields and(!) size == 1. At least
+ # for the common case of a single base class we can
+ # fake the contents by using the whole derived object's
+ # data as base class data.
+ data = nativeValue.GetData()
+ size = nativeType.GetByteSize()
+ error = lldb.SBError()
+ member.laddress = value.laddress
+ member.ldata = data.ReadRawData(error, 0, size)
+ member.isBaseClass = True
+ fields.append(member)
+ return fields
def ptrSize(self):
result = self.target.GetAddressByteSize()
self.ptrSize = lambda: result
return result
- def fromNativeType(self, nativeType):
+ def from_native_type(self, nativeType):
self.check(isinstance(nativeType, lldb.SBType))
- code = nativeType.GetTypeClass()
# eTypeClassInvalid = (0u),
# eTypeClassArray = (1u << 0),
@@ -367,43 +365,41 @@ class Dumper(DumperBase):
# // Define a mask that can be used for any type when finding types
# eTypeClassAny = (0xffffffffu)
- #DumperBase.warn('CURRENT: %s' % self.typeData.keys())
- #DumperBase.warn('FROM NATIVE TYPE: %s' % nativeType.GetName())
- if code == lldb.eTypeClassInvalid:
- return None
+ #self.warn('CURRENT: %s' % self.typeData.keys())
+ #self.warn('FROM NATIVE TYPE: %s' % nativeType.GetName())
- if code == lldb.eTypeClassBuiltin:
- nativeType = nativeType.GetUnqualifiedType()
+ typeid_str = self.native_type_key(nativeType)
+ known_typeid = self.typeid_from_typekey.get(typeid_str, None)
+ if known_typeid is not None:
+ return known_typeid
- if code == lldb.eTypeClassPointer:
- #DumperBase.warn('PTR')
- nativeTargetType = nativeType.GetPointeeType()
- if not nativeTargetType.IsPointerType():
- nativeTargetType = nativeTargetType.GetUnqualifiedType()
- #DumperBase.warn('PTR: %s' % nativeTargetType.name)
- return self.createPointerType(self.fromNativeType(nativeTargetType))
+ code = nativeType.GetTypeClass()
- if code == lldb.eTypeClassReference:
+ if code == lldb.eTypeClassInvalid:
+ typeid = 0
+
+ elif code == lldb.eTypeClassPointer:
+ #self.warn('PTR: %s' % nativeTargetType.name)
+ target_typeid = self.from_native_type(nativeType.GetPointeeType())
+ typeid = self.create_pointer_typeid(target_typeid)
+
+ elif code == lldb.eTypeClassReference:
#DumperBase.warn('REF')
- nativeTargetType = nativeType.GetDereferencedType()
- if not nativeTargetType.IsPointerType():
- nativeTargetType = nativeTargetType.GetUnqualifiedType()
- #DumperBase.warn('REF: %s' % nativeTargetType.name)
- return self.createReferenceType(self.fromNativeType(nativeTargetType))
+ target_typeid = self.from_native_type(nativeType.GetDereferencedType())
+ typeid = self.create_reference_typeid(target_typeid)
- if code == lldb.eTypeClassTypedef:
+ elif code == lldb.eTypeClassTypedef:
#DumperBase.warn('TYPEDEF')
nativeTargetType = nativeType.GetUnqualifiedType()
if hasattr(nativeTargetType, 'GetCanonicalType'):
nativeTargetType = nativeTargetType.GetCanonicalType()
- targetType = self.fromNativeType(nativeTargetType)
- return self.createTypedefedType(targetType, nativeType.GetName(),
- self.nativeTypeId(nativeType))
-
- nativeType = nativeType.GetUnqualifiedType()
- typeName = self.typeName(nativeType)
+ target_typeid = self.from_native_type(nativeTargetType)
+ typeid = self.create_typedefed_typeid(target_typeid, nativeType.GetName(),
+ typeid_str)
- if code in (lldb.eTypeClassArray, lldb.eTypeClassVector):
+ elif code in (lldb.eTypeClassArray, lldb.eTypeClassVector):
+ nativeType = nativeType.GetUnqualifiedType()
+ type_name = nativeType.GetName()
#DumperBase.warn('ARRAY: %s' % nativeType.GetName())
if hasattr(nativeType, 'GetArrayElementType'): # New in 3.8(?) / 350.x
nativeTargetType = nativeType.GetArrayElementType()
@@ -412,141 +408,139 @@ class Dumper(DumperBase):
#DumperBase.warn('BAD: %s ' % nativeTargetType.get_fields_array())
nativeTargetType = nativeType.GetVectorElementType()
count = nativeType.GetByteSize() // nativeTargetType.GetByteSize()
- targetTypeName = nativeTargetType.GetName()
- if targetTypeName.startswith('(anon'):
- typeName = nativeType.GetName()
- pos1 = typeName.rfind('[')
- targetTypeName = typeName[0:pos1].strip()
- #DumperBase.warn("TARGET TYPENAME: %s" % targetTypeName)
- targetType = self.fromNativeType(nativeTargetType)
- targetType.setTdata(targetType.tdata.copy())
- targetType.tdata.name = targetTypeName
- return self.createArrayType(targetType, count)
- if hasattr(nativeType, 'GetVectorElementType'): # New in 3.8(?) / 350.x
+ target_typename = nativeTargetType.GetName()
+ if target_typename.startswith('(anon'):
+ type_name = nativeType.GetName()
+ pos1 = type_name.rfind('[')
+ target_typename = type_name[0:pos1].strip()
+ #DumperBase.warn("TARGET TYPENAME: %s" % target_typename)
+ target_typeid = self.from_native_type(nativeTargetType)
+ #target_typeid.setTdata(target_typeid.tdata.copy())
+ #target_typeid.tdata.name = target_typename
+ typeid = self.create_array_typeid(target_typeid, count)
+ elif hasattr(nativeType, 'GetVectorElementType'): # New in 3.8(?) / 350.x
nativeTargetType = nativeType.GetVectorElementType()
count = nativeType.GetByteSize() // nativeTargetType.GetByteSize()
- targetType = self.fromNativeType(nativeTargetType)
- return self.createArrayType(targetType, count)
- return self.createType(nativeType.GetName())
+ target_typeid = self.from_native_type(nativeTargetType)
+ typeid = self.create_array_typeid(target_typeid, count)
+ else:
+ typeid = self.create_type(nativeType.GetName())
+
+ else:
+ nativeType = nativeType.GetUnqualifiedType()
+ type_name = nativeType.GetName()
- typeId = self.nativeTypeId(nativeType)
- res = self.typeData.get(typeId, None)
- if res is None:
+ typeid = self.typeid_for_string(typeid_str)
+ #if not typeid in self.typeid_cache:
# # This strips typedefs for pointers. We don't want that.
# typeobj.nativeType = nativeType.GetUnqualifiedType()
- tdata = self.TypeData(self, typeId)
- tdata.name = typeName
- tdata.lbitsize = nativeType.GetByteSize() * 8
+ self.type_name_cache[typeid] = type_name
+ self.type_size_cache[typeid] = nativeType.GetByteSize()
+ type_code = None
if code == lldb.eTypeClassBuiltin:
- if utils.isFloatingPointTypeName(typeName):
- tdata.code = TypeCode.Float
- elif utils.isIntegralTypeName(typeName):
- tdata.code = TypeCode.Integral
- elif typeName in ('__int128', 'unsigned __int128'):
- tdata.code = TypeCode.Integral
- elif typeName == 'void':
- tdata.code = TypeCode.Void
- elif typeName == 'wchar_t':
- tdata.code = TypeCode.Integral
- elif typeName in ("char16_t", "char32_t", "char8_t"):
- tdata.code = TypeCode.Integral
+ if utils.isFloatingPointTypeName(type_name):
+ type_code = TypeCode.Float
+ elif utils.isIntegralTypeName(type_name):
+ type_code = TypeCode.Integral
+ elif type_name in ('__int128', 'unsigned __int128'):
+ type_code = TypeCode.Integral
+ elif type_name == 'void':
+ type_code = TypeCode.Void
+ elif type_name == 'wchar_t':
+ type_code = TypeCode.Integral
+ elif type_name in ("char16_t", "char32_t", "char8_t"):
+ type_code = TypeCode.Integral
else:
- self.warn('UNKNOWN TYPE KEY: %s: %s' % (typeName, code))
+ self.warn('UNKNOWN TYPE KEY: %s: %s' % (type_name, code))
elif code == lldb.eTypeClassEnumeration:
- tdata.code = TypeCode.Enum
- tdata.enumDisplay = lambda intval, addr, form: \
+ type_code = TypeCode.Enum
+ self.type_enum_display_cache[typeid] = lambda intval, addr, form: \
self.nativeTypeEnumDisplay(nativeType, intval, form)
elif code in (lldb.eTypeClassComplexInteger, lldb.eTypeClassComplexFloat):
- tdata.code = TypeCode.Complex
+ type_code = TypeCode.Complex
elif code in (lldb.eTypeClassClass, lldb.eTypeClassStruct, lldb.eTypeClassUnion):
- tdata.code = TypeCode.Struct
- tdata.lalignment = lambda: \
- self.nativeStructAlignment(nativeType)
- tdata.lfields = lambda value: \
- self.listMembers(value, nativeType)
- tdata.templateArguments = lambda: \
- self.listTemplateParametersHelper(nativeType)
+ type_code = TypeCode.Struct
elif code == lldb.eTypeClassFunction:
- tdata.code = TypeCode.Function
+ type_code = TypeCode.Function
elif code == lldb.eTypeClassMemberPointer:
- tdata.code = TypeCode.MemberPointer
- # warn('CREATE TYPE: %s' % typeId)
+ type_code = TypeCode.MemberPointer
+
+ if code is not None:
+ self.type_code_cache[typeid] = type_code
+
+ self.type_nativetype_cache[typeid] = nativeType
+ self.typeid_from_typekey[typeid_str] = typeid
+
+ # self.warn('REUSE TYPE: %s' % typeid)
+ return typeid
+
+ def nativeTemplateParameter(self, typeid, index, nativeType):
+ #n = nativeType.GetNumberOfTemplateArguments()
+ #if n != len(stringArgs):
+ # # Something wrong in the debug info.
+ # # Should work in theory, doesn't work in practice.
+ # # Items like std::allocator<std::pair<unsigned int const, float> report 0
+ # # for nativeType.GetNumberOfTemplateArguments() with LLDB 3.8
+ # return stringArgs
+
+ kind = nativeType.GetTemplateArgumentKind(index)
+ # eTemplateArgumentKindNull = 0,
+ # eTemplateArgumentKindType,
+ # eTemplateArgumentKindDeclaration,
+ # eTemplateArgumentKindIntegral,
+ # eTemplateArgumentKindTemplate,
+ # eTemplateArgumentKindTemplateExpansion,
+ # eTemplateArgumentKindExpression,
+ # eTemplateArgumentKindPack
+ if kind == lldb.eTemplateArgumentKindType:
+ innerType = nativeType.GetTemplateArgumentType(index) \
+ .GetUnqualifiedType().GetCanonicalType()
+ return self.Type(self, self.from_native_type(innerType))
+ #elif kind == lldb.eTemplateArgumentKindIntegral:
+ # innerType = nativeType.GetTemplateArgumentType(i).GetUnqualifiedType().GetCanonicalType()
+ # #DumperBase.warn('INNER TYP: %s' % innerType)
+ # basicType = innerType.GetBasicType()
+ # #DumperBase.warn('IBASIC TYP: %s' % basicType)
+ # inner = self.extractTemplateArgument(nativeType.GetName(), i)
+ # exp = '(%s)%s' % (innerType.GetName(), inner)
+ # #DumperBase.warn('EXP : %s' % exp)
+ # val = self.nativeParseAndEvaluate('(%s)%s' % (innerType.GetName(), inner))
+ # # Clang writes 'int' and '0xfffffff' into the debug info
+ # # LLDB manages to read a value of 0xfffffff...
+ # #if basicType == lldb.eBasicTypeInt:
+ # value = val.GetValueAsUnsigned()
+ # if value >= 0x8000000:
+ # value -= 0x100000000
+ # #DumperBase.warn('KIND: %s' % kind)
+ # targs.append(value)
#else:
- # warn('REUSE TYPE: %s' % typeId)
- return self.Type(self, typeId)
-
- def listTemplateParametersHelper(self, nativeType):
- stringArgs = self.listTemplateParameters(nativeType.GetName())
- n = nativeType.GetNumberOfTemplateArguments()
- if n != len(stringArgs):
- # Something wrong in the debug info.
- # Should work in theory, doesn't work in practice.
- # Items like std::allocator<std::pair<unsigned int const, float> report 0
- # for nativeType.GetNumberOfTemplateArguments() with LLDB 3.8
- return stringArgs
-
- targs = []
- for i in range(nativeType.GetNumberOfTemplateArguments()):
- kind = nativeType.GetTemplateArgumentKind(i)
- # eTemplateArgumentKindNull = 0,
- # eTemplateArgumentKindType,
- # eTemplateArgumentKindDeclaration,
- # eTemplateArgumentKindIntegral,
- # eTemplateArgumentKindTemplate,
- # eTemplateArgumentKindTemplateExpansion,
- # eTemplateArgumentKindExpression,
- # eTemplateArgumentKindPack
- if kind == lldb.eTemplateArgumentKindType:
- innerType = nativeType.GetTemplateArgumentType(
- i).GetUnqualifiedType().GetCanonicalType()
- targs.append(self.fromNativeType(innerType))
- #elif kind == lldb.eTemplateArgumentKindIntegral:
- # innerType = nativeType.GetTemplateArgumentType(i).GetUnqualifiedType().GetCanonicalType()
- # #DumperBase.warn('INNER TYP: %s' % innerType)
- # basicType = innerType.GetBasicType()
- # #DumperBase.warn('IBASIC TYP: %s' % basicType)
- # inner = self.extractTemplateArgument(nativeType.GetName(), i)
- # exp = '(%s)%s' % (innerType.GetName(), inner)
- # #DumperBase.warn('EXP : %s' % exp)
- # val = self.nativeParseAndEvaluate('(%s)%s' % (innerType.GetName(), inner))
- # # Clang writes 'int' and '0xfffffff' into the debug info
- # # LLDB manages to read a value of 0xfffffff...
- # #if basicType == lldb.eBasicTypeInt:
- # value = val.GetValueAsUnsigned()
- # if value >= 0x8000000:
- # value -= 0x100000000
- # #DumperBase.warn('KIND: %s' % kind)
- # targs.append(value)
- else:
- #DumperBase.warn('UNHANDLED TEMPLATE TYPE : %s' % kind)
- targs.append(stringArgs[i]) # Best we can do.
+ # #DumperBase.warn('UNHANDLED TEMPLATE TYPE : %s' % kind)
+ # targs.append(stringArgs[i]) # Best we can do.
#DumperBase.warn('TARGS: %s %s' % (nativeType.GetName(), [str(x) for x in targs]))
- return targs
-
- def typeName(self, nativeType):
- # Don't use GetDisplayTypeName since LLDB removed the inline namespace __1
- # https://reviews.llvm.org/D74478
- return nativeType.GetName()
+ #return targs
+ return None
- def nativeTypeId(self, nativeType):
- if nativeType and (nativeType.GetTypeClass() == lldb.eTypeClassTypedef):
+ def native_type_key(self, nativeType):
+ code = nativeType.GetTypeClass()
+ if nativeType and code == lldb.eTypeClassTypedef:
nativeTargetType = nativeType.GetUnqualifiedType()
if hasattr(nativeTargetType, 'GetCanonicalType'):
nativeTargetType = nativeTargetType.GetCanonicalType()
return '%s{%s}' % (nativeType.name, nativeTargetType.name)
- name = self.typeName(nativeType)
+ # Don't use GetDisplayTypeName since LLDB removed the inline namespace __1
+ # https://reviews.llvm.org/D74478
+ name = nativeType.GetName()
if name is None or len(name) == 0:
c = '0'
- elif name == '(anonymous struct)' and nativeType.GetTypeClass() == lldb.eTypeClassStruct:
- c = 's'
- elif name == '(anonymous struct)' and nativeType.GetTypeClass() == lldb.eTypeClassUnion:
- c = 'u'
+ elif name == '(anonymous struct)':
+ c = 's' if code == lldb.eTypeClassStruct else 'u'
else:
return name
fields = nativeType.get_fields_array()
- typeId = c + ''.join(['{%s:%s}' % (f.name, self.nativeTypeId(f.GetType())) for f in fields])
- #DumperBase.warn('NATIVE TYPE ID FOR %s IS %s' % (name, typeId))
- return typeId
+ id_str = c + ''.join(['{%s:%s}' %
+ (f.name, self.typeid_for_string(self.native_type_key(f.GetType())))
+ for f in fields])
+ return id_str
def nativeTypeEnumDisplay(self, nativeType, intval, form):
if hasattr(nativeType, 'get_enum_members_array'):
@@ -575,12 +569,82 @@ class Dumper(DumperBase):
return '(' + ' | '.join(flags) + ') (' + (form % intval) + ')'
return form % intval
- def nativeDynamicTypeName(self, address, baseType):
- return None # FIXME: Seems sufficient, no idea why.
- addr = self.target.ResolveLoadAddress(address)
- ctx = self.target.ResolveSymbolContextForAddress(addr, 0)
- sym = ctx.GetSymbol()
- return sym.GetName()
+ def nativeDynamicType(self, address, base_typeid):
+ return self.nativeDynamicType_2(address, base_typeid)
+
+ def nativeDynamicType_1(self, address, base_typeid):
+ # Solutions 1: Breaks StdUniquePtr and QVariant1 test
+ return base_typeid
+
+ def nativeDynamicType_2(self, address, base_typeid):
+ # Solution 2: ~10% slower in total than Solution 1
+ typename = self.type_name(base_typeid)
+ #self.warn("LOOKING FOR DYN TYPE: 0x%x %s" % (address, typename))
+ #self.warn(" PRETTY: 0x%x %s" % (address, self.prettySymbolByAddress(address)))
+
+ expr = '(void*)%s' % address
+ value = self.target.EvaluateExpression(expr)
+
+ #self.warn("VALUE: %s" % value)
+ if value.GetType().GetName() == "void *":
+ #self.warn("NO DYN TYPE: %s" % value)
+ return base_typeid
+
+ dvalue = value.Dereference()
+ #self.warn("DVALUE: %s" % value)
+ sbtype = dvalue.GetType()
+ #self.warn("TYPE: %s" % sbtype)
+
+ #self.warn("OUTPUT: %s" % output)
+ #self.warn("DYNTYPE: %s" % dyn_typename)
+ return self.from_native_type(sbtype)
+
+ def nativeDynamicType_3(self, address, base_typeid):
+ # Solution 3: Doesn't improve over 1
+ typename = self.type_name(base_typeid)
+ self.warn("LOOKING FOR DYN TYPE: 0x%x %s" % (address, typename))
+ #self.warn(" PRETTY: 0x%x %s" % (address, self.prettySymbolByAddress(address)))
+ nativeType = self.type_nativetype_cache.get(base_typeid, None)
+ #self.warn(" NATIVE BASE %s" % nativeType)
+ if nativeType is None:
+ return base_typeid
+ #versionValue = self.target.EvaluateExpression('qtHookData[2]').GetNonSyntheticValue()
+ addr = lldb.SBAddress(address, self.target)
+ value = self.target.CreateValueFromAddress('x', addr, nativeType)
+ self.warn(" VALUE %s" % value)
+ return base_typeid
+
+ def nativeDynamicType_4(self, address, base_typeid):
+ #self.warn("RESULT: %s" % result)
+ #self.warn("ADDRESS: 0x%x" % address)
+
+ #thread = self.currentThread()
+ #frame = thread.GetFrameAtIndex(0)
+ #expr = '(void*)%s' % address
+ #value = self.target.EvaluateExpression(expr)
+ #sbtype = self.lookupNativeType(typename)
+ #addr = self.target.ResolveLoadAddress(address)
+ #addr = lldb.SBAddress(address, self.target)
+ #value = self.target.CreateValueFromAddress('x', addr, sbtype)
+ #x = lldb::DynamicValueType()
+ #lldb.eNoDynamicValues
+ #lldb.eDynamicCanRunTarget
+ #lldb.eDynamicDontRunTarget
+ #dyn_value = value.GetDynamicValue(lldb.eDynamicDontRunTarget)
+ #typ = dyn_value.GetType()
+ self.warn("GOT DYN VALUE: %s" % dyn_value)
+ #self.warn("GOT TYPE: %s FOR OBJECT AT 0x%x" % (typ, address))
+ return self.from_native_type(typ)
+
+ #result = lldb.SBCommandReturnObject()
+ #cmd = 'p (void*)%s' % address
+ #self.debugger.GetCommandInterpreter().HandleCommand(cmd, result)
+ #if not result.Succeeded():
+ # return self.Type(self, typeid)
+ #output = result.GetOutput().strip()
+ #dyn_typename = output[1:output.find('$') - 4]
+ #sbtype = self.lookupNativeType(dyn_typename)
+
def stateName(self, s):
try:
@@ -638,11 +702,11 @@ class Dumper(DumperBase):
#DumperBase.warn(' -> %s' % result)
return self.fromNativeValue(result)
- def pokeValue(self, typeName, *args):
+ def pokeValue(self, type_name, *args):
thread = self.currentThread()
frame = thread.GetFrameAtIndex(0)
inner = ','.join(args)
- value = frame.EvaluateExpression(typeName + '{' + inner + '}')
+ value = frame.EvaluateExpression(type_name + '{' + inner + '}')
#DumperBase.warn(' TYPE: %s' % value.type)
#DumperBase.warn(' ADDR: 0x%x' % value.address)
#DumperBase.warn(' VALUE: %s' % value)
@@ -830,8 +894,6 @@ class Dumper(DumperBase):
#DumperBase.warn('RECURSE PTR')
typeobj = self.lookupNativeType(name[:-1].strip())
if typeobj is not None:
- #DumperBase.warn('RECURSE RESULT X: %s' % typeobj)
- self.fromNativeType(typeobj.GetPointerType())
#DumperBase.warn('RECURSE RESULT: %s' % typeobj.GetPointerType())
return typeobj.GetPointerType()
@@ -1289,14 +1351,12 @@ class Dumper(DumperBase):
def findSymbol(self, symbolName):
return self.target.FindFirstGlobalVariable(symbolName)
- def warn(self, msg):
- self.put('{name="%s",value="",type="",numchild="0"},' % toCString(msg))
-
def fetchVariables(self, args):
- (ok, res) = self.tryFetchInterpreterVariables(args)
- if ok:
- self.reportResult(res, args)
- return
+ start_time = time.perf_counter()
+ #(ok, res) = self.tryFetchInterpreterVariables(args)
+ #if ok:
+ # self.reportResult(res, args)
+ # return
self.setVariableFetchingOptions(args)
@@ -1360,13 +1420,15 @@ class Dumper(DumperBase):
# This can happen for unnamed function parameters with
# default values: void foo(int = 0)
continue
- value = self.fromNativeFrameValue(val)
+ value = self.fromNativeValue(val)
variables.append(value)
self.handleLocals(variables)
self.handleWatches(args)
- self.put('],partial="%d"' % isPartial)
+ run_time = time.perf_counter() - start_time
+
+ self.put('],partial="%d",runtime="%s"' % (isPartial, run_time))
self.reportResult(self.takeOutput(), args)
@@ -1987,14 +2049,14 @@ class Dumper(DumperBase):
value = self.hexdecode(args['value'])
simpleType = int(args['simpleType'])
lhs = self.findValueByExpression(expr)
- typeName = lhs.GetType().GetName()
- typeName = typeName.replace('::', '__')
- pos = typeName.find('<')
+ type_name = lhs.GetType().GetName()
+ type_name = type_name.replace('::', '__')
+ pos = type_name.find('<')
if pos != -1:
- typeName = typeName[0:pos]
- if typeName in self.qqEditable and not simpleType:
+ type_name = type_name[0:pos]
+ if type_name in self.qqEditable and not simpleType:
expr = self.parseAndEvaluate(expr)
- self.qqEditable[typeName](self, expr, value)
+ self.qqEditable[type_name](self, expr, value)
else:
self.parseAndEvaluate(expr + '=' + value)
self.reportResult(self.describeError(error), args)
@@ -2098,10 +2160,10 @@ class Tester(Dumper):
if 'QT_CREATOR_LLDB_PROCESS' in os.environ:
# Initialize Qt Creator dumper
- try:
+ #try:
theDumper = Dumper()
- except Exception as error:
- print('@\nstate="enginesetupfailed",error="{}"@\n'.format(error))
+ #except Exception as error:
+ # print('@\nstate="enginesetupfailed",error="{}"@\n'.format(error))
# ------------------------------ For use in LLDB ------------------------------
diff --git a/share/qtcreator/debugger/qttypes.py b/share/qtcreator/debugger/qttypes.py
index 06e7d47325..af99534c9b 100644
--- a/share/qtcreator/debugger/qttypes.py
+++ b/share/qtcreator/debugger/qttypes.py
@@ -221,15 +221,15 @@ def qdump__Qt__ItemDataRole(d, value):
def qdump__QStandardItemData(d, value):
- d.createType('@Qt::ItemDataRole') # warm up cache
+ #d.createType('@Qt::ItemDataRole') # warm up cache
role, pad, val = value.split('{@Qt::ItemDataRole}@{@QVariant}')
d.putPairContents(role.value(), (role, val), 'role', 'value')
def qdump__QStandardItem(d, value):
- d.createType('@QStandardItemData') # warm up cache
- d.createType('@QStandardItem')
- d.createType('@QStandardItem*')
+ #d.createType('@QStandardItemData') # warm up cache
+ #d.createType('@QStandardItem')
+ #d.createType('@QStandardItem*')
vtable, dptr = value.split('pp')
if d.qtVersion() >= 0x060000:
@@ -549,14 +549,11 @@ def qdump__QDir(d, value):
#d.putCallItem('absolutePath', '@QString', value, 'absolutePath')
#d.putCallItem('canonicalPath', '@QString', value, 'canonicalPath')
with SubItem(d, 'absolutePath'):
- typ = d.lookupType(ns + 'QString')
- d.putItem(d.createValue(privAddress + absoluteDirEntryOffset, typ))
+ d.putItem(d.createValue(privAddress + absoluteDirEntryOffset, '@QString'))
with SubItem(d, 'entryInfoList'):
- typ = d.lookupType(ns + 'QFileInfo')
- qdumpHelper_QList(d, privAddress + fileInfosOffset, typ)
+ qdumpHelper_QList(d, privAddress + fileInfosOffset, '@QFileInfo')
with SubItem(d, 'entryList'):
- typ = d.lookupType(ns + 'QStringList')
- d.putItem(d.createValue(privAddress + filesOffset, typ))
+ d.putItem(d.createValue(privAddress + filesOffset, '@QStringList'))
d.putFields(value)
@@ -1095,14 +1092,15 @@ def qform__QList():
def qdump__QList(d, value):
- return qdumpHelper_QList(d, value, d.createType(value.type[0]))
+ return qdumpHelper_QList(d, value, value.type[0])
def qdump__QVariantList(d, value):
- qdumpHelper_QList(d, value, d.createType('@QVariant'))
+ qdumpHelper_QList(d, value, '@QVariant')
-def qdumpHelper_QList(d, value, innerType):
+def qdumpHelper_QList(d, value, inner_typish):
+ innerType = d.createType(inner_typish)
data, size = d.listData(value, check=True)
d.putItemCount(size)
@@ -1224,7 +1222,8 @@ def qdump__QLocale(d, value):
# index = int(value['d']['d']['m_data']...)
#d.check(index >= 0)
#d.check(index <= qqLocalesCount)
- if d.qtVersion() < 0x50000:
+ qtVersion = d.qtVersion()
+ if qtVersion < 0x50000:
d.putStringValue(d.call('const char *', value, 'name'))
d.putPlainChildren(value)
return
@@ -1238,14 +1237,20 @@ def qdump__QLocale(d, value):
= d.split('2s{short}2s'
+ '{@QChar}{@QChar}{short}{@QChar}{@QChar}'
+ '{@QChar}{@QChar}{@QChar}', data)
+
+ prefix = ns + 'QLocale::'
try:
- d.putStringValue(d.call('const char *', value, 'name'))
+ if qtVersion >= 0x060700:
+ res = d.call('const char *', value, 'name', prefix + 'TagSeparator::Underscore')
+ else:
+ res = d.call('const char *', value, 'name')
+ d.putStringValue(res)
except:
pass
+
d.putExpandable()
if d.isExpanded():
with Children(d):
- prefix = ns + 'QLocale::'
d.putSubItem('country', d.createValue(countryId, prefix + 'Country'))
d.putSubItem('language', d.createValue(languageId, prefix + 'Language'))
d.putSubItem('numberOptions', d.createValue(numberOptions, prefix + 'NumberOptions'))
@@ -1425,7 +1430,9 @@ if False:
d.putSpecialValue('minimumitemcount', 0)
-def qdump__QPair(d, value):
+# FIXME: Qt 5
+# remvign the _xxxx makes GDB work with Qt 5 but breaks LLDB
+def qdump__QPair_xxxx(d, value):
typeCode = '{%s}@{%s}' % (value.type[0].name, value.type[1].name)
first, pad, second = value.split(typeCode)
with Children(d):
@@ -1857,7 +1864,7 @@ def qdump__QStringRef(d, value):
def qdump__QStringList(d, value):
- qdumpHelper_QList(d, value, d.createType('@QString'))
+ qdumpHelper_QList(d, value, '@QString')
d.putBetterType(value.type)
@@ -2304,22 +2311,22 @@ def qdump__QVector(d, value):
if d.qtVersion() >= 0x060000:
data, length = d.listData(value)
d.putItemCount(length)
- d.putPlotData(data, length, d.createType(value.type.ltarget[0]))
+ d.putPlotData(data, length, value.type.target()[0])
# g++ 9.3 does not add the template parameter list to the debug info.
# Fake it for the common case:
if value.type.name == d.qtNamespace() + "QVector":
- d.putBetterType(value.type.name + '<' + value.type.ltarget[0].name + '>')
+ d.putBetterType(value.type.name + '<' + value.type.target()[0].name + '>')
else:
data, length = d.vectorData(value)
d.putItemCount(length)
- d.putPlotData(data, length, d.createType(value.type[0]))
+ d.putPlotData(data, length, value.type[0])
if False:
def qdump__QObjectConnectionList(d, value):
data, length = d.vectorData(value)
d.putItemCount(length)
- d.putPlotData(data, length, d.createType('@QObjectPrivate::ConnectionList'))
+ d.putPlotData(data, length, '@QObjectPrivate::ConnectionList')
def qdump__QVarLengthArray(d, value):
@@ -2913,15 +2920,13 @@ def qdump_64__QJSValue_6(d, value):
elif typ > 7:
val = d.Value(d)
val.ldata = struct.pack('q', dd ^ 0xfffc000000000000)
- val._type = d.createType('double')
- d.putItem(val)
+ d.putItem(val.cast('double'))
d.putType(value.type.name + ' (double)')
elif typ <= 3: # Heap
if dd & 1: # String
val = d.Value(d)
val.ldata = struct.pack('q', dd & ~1)
- val._type = d.createType('@QString*')
- d.putItem(val)
+ d.putItem(val.cast('@QString*'))
d.putType(value.type.name + ' (QString)')
else:
# FIXME: Arrays, Objects missing.
@@ -2955,16 +2960,13 @@ def qdump_64__QJSValue_6(d, value):
val = d.Value(d)
val.ldata = struct.pack('q', pointer)
if typ == 1:
- val._type = d.createType('double*')
- d.putItem(val)
+ d.putItem(val.cast('double*'))
d.putType(value.type.name + ' (double)')
elif typ == 3:
- val._type = d.createType('@QV4::Value*')
- d.putItem(val)
+ d.putItem(val.cast('@QV4::Value*'))
d.putType(value.type.name + ' (QV4::Value)')
elif typ == 5:
- val._type = d.createType('@QString*')
- d.putItem(val)
+ d.putItem(val.cast('@QString*'))
d.putType(value.type.name + ' (QString)')
else:
@@ -3538,7 +3540,7 @@ def qdump__QCborValue(d, value):
d.putPlainChildren(value)
def qdump__QCborValue_proxy(d, value):
- item_data, container_ptr, item_type, is_cbor = value.data()
+ item_data, container_ptr, item_type, is_cbor = value.ldata
def typename(key, is_cbor):
if is_cbor: