2016-10-06 13:36:02 +02:00
|
|
|
############################################################################
|
|
|
|
#
|
|
|
|
# Copyright (C) 2016 The Qt Company Ltd.
|
|
|
|
# Contact: https://www.qt.io/licensing/
|
|
|
|
#
|
|
|
|
# This file is part of Qt Creator.
|
|
|
|
#
|
|
|
|
# Commercial License Usage
|
|
|
|
# Licensees holding valid commercial Qt licenses may use this file in
|
|
|
|
# accordance with the commercial license agreement provided with the
|
|
|
|
# Software or, alternatively, in accordance with the terms contained in
|
|
|
|
# a written agreement between you and The Qt Company. For licensing terms
|
|
|
|
# and conditions see https://www.qt.io/terms-conditions. For further
|
|
|
|
# information use the contact form at https://www.qt.io/contact-us.
|
|
|
|
#
|
|
|
|
# GNU General Public License Usage
|
|
|
|
# Alternatively, this file may be used under the terms of the GNU
|
|
|
|
# General Public License version 3 as published by the Free Software
|
|
|
|
# Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
|
|
|
|
# included in the packaging of this file. Please review the following
|
|
|
|
# information to ensure the GNU General Public License requirements will
|
|
|
|
# be met: https://www.gnu.org/licenses/gpl-3.0.html.
|
|
|
|
#
|
|
|
|
############################################################################
|
|
|
|
|
|
|
|
import inspect
|
|
|
|
import os
|
|
|
|
import sys
|
|
|
|
import cdbext
|
|
|
|
|
|
|
|
sys.path.insert(1, os.path.dirname(os.path.abspath(inspect.getfile(inspect.currentframe()))))
|
|
|
|
|
|
|
|
from dumper import *
|
|
|
|
|
|
|
|
class Dumper(DumperBase):
|
|
|
|
def __init__(self):
|
|
|
|
DumperBase.__init__(self)
|
|
|
|
|
|
|
|
self.outputLock = threading.Lock()
|
|
|
|
|
|
|
|
self.isCdb = True
|
|
|
|
self.expandedINames = {}
|
|
|
|
self.passExceptions = False
|
|
|
|
self.showQObjectNames = False
|
|
|
|
self.autoDerefPointers = True
|
|
|
|
self.useDynamicType = True
|
|
|
|
self.useFancy = True
|
|
|
|
self.formats = {}
|
|
|
|
self.typeformats = {}
|
|
|
|
self.currentContextValue = None
|
|
|
|
|
|
|
|
self.currentIName = None
|
|
|
|
self.currentValue = ReportItem()
|
|
|
|
self.currentType = ReportItem()
|
|
|
|
self.currentNumChild = None
|
|
|
|
self.currentMaxNumChild = None
|
|
|
|
self.currentPrintsAddress = True
|
|
|
|
self.currentChildType = None
|
|
|
|
self.currentChildNumChild = -1
|
|
|
|
self.currentWatchers = {}
|
|
|
|
|
|
|
|
def fromNativeValue(self, nativeValue):
|
|
|
|
val = self.Value(self)
|
|
|
|
val.nativeValue = nativeValue
|
|
|
|
val.type = self.fromNativeType(nativeValue.type())
|
|
|
|
val.lIsInScope = True
|
|
|
|
val.laddress = nativeValue.address()
|
|
|
|
return val
|
|
|
|
|
|
|
|
def fromNativeType(self, nativeType):
|
|
|
|
typeobj = self.Type(self)
|
|
|
|
typeobj.nativeType = nativeType
|
|
|
|
typeobj.name = nativeType.name()
|
|
|
|
typeobj.lbitsize = nativeType.bitsize()
|
|
|
|
typeobj.code = nativeType.code()
|
|
|
|
return typeobj
|
|
|
|
|
|
|
|
def nativeTypeFields(self, nativeType):
|
|
|
|
fields = []
|
|
|
|
for nativeField in nativeType.fields():
|
|
|
|
field = self.Field(self)
|
|
|
|
field.name = nativeField.name()
|
|
|
|
field.parentType = self.fromNativeType(nativeType)
|
|
|
|
field.ltype = self.fromNativeType(nativeField.type())
|
|
|
|
field.lbitsize = nativeField.bitsize()
|
|
|
|
field.lbitpos = nativeField.bitpos()
|
|
|
|
fields.append(field)
|
|
|
|
return fields
|
|
|
|
|
|
|
|
def nativeTypeUnqualified(self, nativeType):
|
|
|
|
return self.fromNativeType(nativeType.unqualified())
|
|
|
|
|
|
|
|
def nativeTypePointer(self, nativeType):
|
|
|
|
return self.fromNativeType(nativeType.target())
|
|
|
|
|
|
|
|
def nativeTypeStripTypedefs(self, typeobj):
|
|
|
|
return self.fromNativeType(nativeType.stripTypedef())
|
|
|
|
|
|
|
|
def nativeTypeFirstBase(self, nativeType):
|
|
|
|
return None
|
|
|
|
|
|
|
|
def nativeTypeEnumDisplay(self, nativeType, intval):
|
|
|
|
# TODO: generate fake value
|
|
|
|
return None
|
|
|
|
|
|
|
|
def enumExpression(self, enumType, enumValue):
|
|
|
|
ns = self.qtNamespace()
|
|
|
|
return ns + "Qt::" + enumType + "(" \
|
|
|
|
+ ns + "Qt::" + enumType + "::" + enumValue + ")"
|
|
|
|
|
|
|
|
def pokeValue(self, typeName, *args):
|
|
|
|
return None
|
|
|
|
|
|
|
|
def parseAndEvaluate(self, exp):
|
|
|
|
return cdbext.parseAndEvaluate(exp)
|
|
|
|
|
|
|
|
def nativeTypeTemplateArgument(self, nativeType, position, numeric = False):
|
|
|
|
return self.fromNativeType(nativeType.templateArgument(position, numeric))
|
|
|
|
|
|
|
|
def nativeTypeDereference(self, nativeType):
|
|
|
|
return self.fromNativeType(nativeType.target())
|
|
|
|
|
|
|
|
def nativeTypeTarget(self, nativeType):
|
|
|
|
return self.fromNativeType(nativeType.target())
|
|
|
|
|
|
|
|
def isWindowsTarget(self):
|
|
|
|
return True
|
|
|
|
|
|
|
|
def isQnxTarget(self):
|
|
|
|
return False
|
|
|
|
|
|
|
|
def isArmArchitecture(self):
|
|
|
|
return False
|
|
|
|
|
|
|
|
def isMsvcTarget(self):
|
|
|
|
return True
|
|
|
|
|
|
|
|
def qtVersionAndNamespace(self):
|
|
|
|
return ('', 0x50700) #FIXME: use a general approach in dumper or qttypes
|
|
|
|
|
|
|
|
def qtNamespace(self):
|
|
|
|
return self.qtVersionAndNamespace()[0]
|
|
|
|
|
|
|
|
def qtVersion(self):
|
|
|
|
self.qtVersionAndNamespace()
|
|
|
|
return self.qtVersionAndNamespace()[1]
|
|
|
|
|
|
|
|
def qtTypeInfoVersion(self):
|
|
|
|
return None
|
|
|
|
|
|
|
|
def ptrSize(self):
|
|
|
|
return cdbext.pointerSize()
|
|
|
|
|
|
|
|
def put(self, stuff):
|
|
|
|
self.output += stuff
|
|
|
|
|
|
|
|
def lookupNativeType(self, name):
|
|
|
|
return cdbext.lookupType(name)
|
|
|
|
|
|
|
|
def currentThread(self):
|
|
|
|
return None
|
|
|
|
|
|
|
|
def currentFrame(self):
|
|
|
|
return None
|
|
|
|
|
|
|
|
def reportResult(self, result, args):
|
|
|
|
self.report('result={%s}' % (result))
|
|
|
|
|
|
|
|
def readRawMemory(self, address, size):
|
|
|
|
return cdbext.readRawMemory(address, size)
|
|
|
|
|
|
|
|
def findStaticMetaObject(self, typeName):
|
|
|
|
symbolName = self.mangleName(typeName + '::staticMetaObject')
|
|
|
|
symbol = self.target.FindFirstGlobalVariable(symbolName)
|
|
|
|
return symbol.AddressOf().GetValueAsUnsigned() if symbol.IsValid() else 0
|
|
|
|
|
|
|
|
def warn(self, msg):
|
|
|
|
self.put('{name="%s",value="",type="",numchild="0"},' % msg)
|
|
|
|
|
|
|
|
def fetchVariables(self, args):
|
|
|
|
(ok, res) = self.tryFetchInterpreterVariables(args)
|
|
|
|
if ok:
|
|
|
|
self.reportResult(res, args)
|
|
|
|
return
|
|
|
|
|
|
|
|
self.expandedINames = set(args.get('expanded', []))
|
|
|
|
self.autoDerefPointers = int(args.get('autoderef', '0'))
|
|
|
|
self.useDynamicType = int(args.get('dyntype', '0'))
|
|
|
|
self.useFancy = int(args.get('fancy', '0'))
|
|
|
|
self.passExceptions = int(args.get('passexceptions', '0'))
|
|
|
|
self.showQObjectNames = int(args.get('qobjectnames', '0'))
|
|
|
|
self.currentWatchers = args.get('watchers', {})
|
|
|
|
self.typeformats = args.get('typeformats', {})
|
|
|
|
self.formats = args.get('formats', {})
|
|
|
|
|
|
|
|
self.output = ''
|
|
|
|
partialVariable = args.get('partialvar', "")
|
|
|
|
isPartial = len(partialVariable) > 0
|
|
|
|
|
|
|
|
self.currentIName = 'local'
|
|
|
|
self.put('data=[')
|
|
|
|
self.anonNumber = 0
|
|
|
|
|
|
|
|
variables = []
|
|
|
|
for val in cdbext.listOfLocals():
|
|
|
|
self.currentContextValue = val
|
|
|
|
name = val.name()
|
|
|
|
value = self.fromNativeValue(val)
|
|
|
|
value.name = name
|
|
|
|
variables.append(value)
|
|
|
|
|
|
|
|
self.handleLocals(variables)
|
|
|
|
self.handleWatches(args)
|
|
|
|
|
|
|
|
self.put('],partial="%d"' % isPartial)
|
|
|
|
self.reportResult(self.output, args)
|
|
|
|
|
|
|
|
def report(self, stuff):
|
2016-10-07 11:13:11 +02:00
|
|
|
sys.stdout.write(stuff + "\n")
|
2016-10-06 13:36:02 +02:00
|
|
|
|
|
|
|
def loadDumpers(self, args):
|
|
|
|
msg = self.setupDumpers()
|
|
|
|
self.reportResult(msg, args)
|
|
|
|
|
|
|
|
def findValueByExpression(self, exp):
|
|
|
|
return cdbext.parseAndEvaluate(exp)
|
|
|
|
|
|
|
|
def nativeDynamicTypeName(self, address, baseType):
|
|
|
|
return None # FIXME: Seems sufficient, no idea why.
|