Debugger: Move some global variables to the Dumper class

Change-Id: I5c8fd8a48f27ac70e6e39f645d64dcd788752e73
Reviewed-by: hjk <hjk121@nokiamail.com>
This commit is contained in:
hjk
2013-10-30 15:07:54 +01:00
parent f9ff630346
commit e176013140
6 changed files with 295 additions and 282 deletions

View File

@@ -41,44 +41,6 @@ else:
verbosity = 0 verbosity = 0
verbosity = 1 verbosity = 1
qqStringCutOff = 10000
# This is a cache mapping from 'type name' to 'display alternatives'.
qqFormats = {}
# This is a cache of all known dumpers.
qqDumpers = {}
# This is a cache of all dumpers that support writing.
qqEditable = {}
# This is an approximation of the Qt Version found
qqVersion = None
# This keeps canonical forms of the typenames, without array indices etc.
qqStripForFormat = {}
def stripForFormat(typeName):
global qqStripForFormat
if typeName in qqStripForFormat:
return qqStripForFormat[typeName]
stripped = ""
inArray = 0
for c in stripClassTag(typeName):
if c == '<':
break
if c == ' ':
continue
if c == '[':
inArray += 1
elif c == ']':
inArray -= 1
if inArray and ord(c) >= 48 and ord(c) <= 57:
continue
stripped += c
qqStripForFormat[typeName] = stripped
return stripped
def hasPlot(): def hasPlot():
fileName = "/usr/bin/gnuplot" fileName = "/usr/bin/gnuplot"
return os.path.isfile(fileName) and os.access(fileName, os.X_OK) return os.path.isfile(fileName) and os.access(fileName, os.X_OK)
@@ -261,6 +223,44 @@ class DumperBase:
self.isGdb = False self.isGdb = False
self.isLldb = False self.isLldb = False
# Later set, or not set:
# cachedQtVersion
self.stringCutOff = 10000
# This is a cache mapping from 'type name' to 'display alternatives'.
self.qqFormats = {}
# This is a cache of all known dumpers.
self.qqDumpers = {}
# This is a cache of all dumpers that support writing.
self.qqEditable = {}
# This keeps canonical forms of the typenames, without array indices etc.
self.cachedFormats = {}
def stripForFormat(self, typeName):
if typeName in self.cachedFormats:
return self.cachedFormats[typeName]
stripped = ""
inArray = 0
for c in stripClassTag(typeName):
if c == '<':
break
if c == ' ':
continue
if c == '[':
inArray += 1
elif c == ']':
inArray -= 1
if inArray and ord(c) >= 48 and ord(c) <= 57:
continue
stripped += c
self.cachedFormats[typeName] = stripped
return stripped
def is32bit(self): def is32bit(self):
return self.ptrSize() == 4 return self.ptrSize() == 4
@@ -268,7 +268,7 @@ class DumperBase:
if limit is None: if limit is None:
return size return size
if limit == 0: if limit == 0:
return min(size, qqStringCutOff) return min(size, self.stringCutOff)
return min(size, limit) return min(size, limit)
def byteArrayDataHelper(self, addr): def byteArrayDataHelper(self, addr):
@@ -372,10 +372,11 @@ class DumperBase:
return self.putValue(self.encodeString(value), Hex4EncodedLittleEndian) return self.putValue(self.encodeString(value), Hex4EncodedLittleEndian)
def putMapName(self, value): def putMapName(self, value):
if str(value.type) == self.ns + "QString": ns = self.qtNamespace()
if str(value.type) == ns + "QString":
self.put('key="%s",' % self.encodeString(value)) self.put('key="%s",' % self.encodeString(value))
self.put('keyencoded="%s",' % Hex4EncodedLittleEndian) self.put('keyencoded="%s",' % Hex4EncodedLittleEndian)
elif str(value.type) == self.ns + "QByteArray": elif str(value.type) == ns + "QByteArray":
self.put('key="%s",' % self.encodeByteArray(value)) self.put('key="%s",' % self.encodeByteArray(value))
self.put('keyencoded="%s",' % Hex2EncodedLatin1) self.put('keyencoded="%s",' % Hex2EncodedLatin1)
else: else:
@@ -416,9 +417,9 @@ class DumperBase:
def encodeCArray(self, p, innerType, suffix): def encodeCArray(self, p, innerType, suffix):
t = self.lookupType(innerType) t = self.lookupType(innerType)
p = p.cast(t.pointer()) p = p.cast(t.pointer())
limit = self.findFirstZero(p, qqStringCutOff) limit = self.findFirstZero(p, self.stringCutOff)
s = self.readMemory(p, limit * t.sizeof) s = self.readMemory(p, limit * t.sizeof)
if limit > qqStringCutOff: if limit > self.stringCutOff:
s += suffix s += suffix
return s return s
@@ -503,6 +504,14 @@ class DumperBase:
return type == "QStringList" and self.qtVersion() >= 0x050000 return type == "QStringList" and self.qtVersion() >= 0x050000
def currentItemFormat(self, type = None):
format = self.formats.get(self.currentIName)
if format is None:
if type is None:
type = self.currentType
needle = self.stripForFormat(str(type))
format = self.typeformats.get(needle)
return format
def cleanAddress(addr): def cleanAddress(addr):
if addr is None: if addr is None:

View File

@@ -298,57 +298,9 @@ class ScanStackCommand(gdb.Command):
ScanStackCommand() ScanStackCommand()
def registerDumper(funcname, function):
global qqDumpers, qqFormats, qqEditable
try:
#warn("FUNCTION: %s " % funcname)
#funcname = function.func_name
if funcname.startswith("qdump__"):
type = funcname[7:]
qqDumpers[type] = function
qqFormats[type] = qqFormats.get(type, "")
elif funcname.startswith("qform__"):
type = funcname[7:]
formats = ""
try:
formats = function()
except:
pass
qqFormats[type] = formats
elif funcname.startswith("qedit__"):
type = funcname[7:]
try:
qqEditable[type] = function
except:
pass
except:
pass
def bbsetup(args = ''): def bbsetup(args = ''):
global qqDumpers, qqFormats, qqEditable, typeCache print(theDumper.bbsetup())
qqDumpers = {}
qqFormats = {}
qqEditable = {}
typeCache = {}
module = sys.modules[__name__]
#warn("KEYS: %s " % module.__dict__.keys())
for name in module.__dict__.keys():
#warn("KEY: %s " % name)
#warn("FUNCT: %s " % module.__dict__[name])
registerDumper(name, module.__dict__[name])
result = "dumpers=["
#qqNs = qtNamespace() # This is too early
for key, value in qqFormats.items():
if key in qqEditable:
result += '{type="%s",formats="%s",editable="true"},' % (key, value)
else:
result += '{type="%s",formats="%s"},' % (key, value)
result += ']'
#result += ',namespace="%s"' % qqNs
print(result)
return result
registerCommand("bbsetup", bbsetup) registerCommand("bbsetup", bbsetup)
@@ -377,18 +329,8 @@ class PlainDumper:
for child in children: for child in children:
d.putSubItem(child[0], child[1]) d.putSubItem(child[0], child[1])
def importPlainDumper(printer):
global qqDumpers, qqFormats
name = printer.name.replace("::", "__")
qqDumpers[name] = PlainDumper(printer)
qqFormats[name] = ""
def importPlainDumpers(args): def importPlainDumpers(args):
return theDumper.importPlainDumpers()
for obj in gdb.objfiles():
for printers in obj.pretty_printers + gdb.pretty_printers:
for printer in printers.subprinters:
importPlainDumper(printer)
registerCommand("importPlainDumpers", importPlainDumpers) registerCommand("importPlainDumpers", importPlainDumpers)
@@ -651,27 +593,6 @@ def value(expr):
Value = gdb.Value Value = gdb.Value
qqNs = None
def qtNamespace():
# FIXME: This only works when call from inside a Qt function frame.
global qqNs
if not qqNs is None:
return qqNs
try:
str = gdb.execute("ptype QString::Null", to_string=True)
# The result looks like:
# "type = const struct myns::QString::Null {"
# " <no data fields>"
# "}"
pos1 = str.find("struct") + 7
pos2 = str.find("QString::Null")
if pos1 > -1 and pos2 > -1:
qqNs = str[pos1:pos2]
return qqNs
return ""
except:
return ""
def stripTypedefs(type): def stripTypedefs(type):
type = type.unqualified() type = type.unqualified()
@@ -698,23 +619,8 @@ class LocalItem:
####################################################################### #######################################################################
def bbedit(args): def bbedit(args):
global qqEditable #(type, expr, value) = args.split(",")
(type, expr, value) = args.split(",") theDumper.bbedit(args.split(","))
type = b16decode(type)
ns = qtNamespace()
if type.startswith(ns):
type = type[len(ns):]
type = type.replace("::", "__")
pos = type.find('<')
if pos != -1:
type = type[0:pos]
expr = b16decode(expr)
value = b16decode(value)
#warn("EDIT: %s %s %s %s: " % (pos, type, expr, value))
if qqEditable.has_key(type):
qqEditable[type](expr, value)
else:
gdb.execute("set (%s)=%s" % (expr, value))
registerCommand("bbedit", bbedit) registerCommand("bbedit", bbedit)
@@ -781,7 +687,9 @@ class Dumper(DumperBase):
# These values will be kept between calls to 'run'. # These values will be kept between calls to 'run'.
self.isGdb = True self.isGdb = True
self.childEventAddress = None self.childEventAddress = None
self.cachedQtVersion = None
# Later set, or not set:
#self.cachedQtVersion
def run(self, args): def run(self, args):
self.output = [] self.output = []
@@ -841,9 +749,7 @@ class Dumper(DumperBase):
self.partialUpdate = "partial" in options self.partialUpdate = "partial" in options
self.tooltipOnly = "tooltiponly" in options self.tooltipOnly = "tooltiponly" in options
self.noLocals = "nolocals" in options self.noLocals = "nolocals" in options
self.ns = qtNamespace() #warn("NAMESPACE: '%s'" % self.qtNamespace())
#warn("NAMESPACE: '%s'" % self.ns)
#warn("VARIABLES: %s" % varList) #warn("VARIABLES: %s" % varList)
#warn("EXPANDED INAMES: %s" % self.expandedINames) #warn("EXPANDED INAMES: %s" % self.expandedINames)
#warn("WATCHERS: %s" % watchers) #warn("WATCHERS: %s" % watchers)
@@ -1209,10 +1115,14 @@ class Dumper(DumperBase):
def selectedInferior(self): def selectedInferior(self):
try: try:
# gdb.Inferior is new in gdb 7.2 # gdb.Inferior is new in gdb 7.2
return gdb.selected_inferior() self.cachedInferior = gdb.selected_inferior()
except: except:
# Pre gdb 7.4. Right now we don't have more than one inferior anyway. # Pre gdb 7.4. Right now we don't have more than one inferior anyway.
return gdb.inferiors()[0] self.cachedInferior = gdb.inferiors()[0]
# Memoize result.
self.selectedInferior = lambda: self.cachedInferior
return self.cachedInferior
def readRawMemory(self, addr, size): def readRawMemory(self, addr, size):
mem = self.selectedInferior().read_memory(addr, size) mem = self.selectedInferior().read_memory(addr, size)
@@ -1289,16 +1199,20 @@ class Dumper(DumperBase):
return xrange(min(toInteger(self.currentMaxNumChild), toInteger(self.currentNumChild))) return xrange(min(toInteger(self.currentMaxNumChild), toInteger(self.currentNumChild)))
def qtVersion(self): def qtVersion(self):
if self.cachedQtVersion is None: try:
self.cachedQtVersion = extractQtVersion()
except:
try: try:
self.cachedQtVersion = extractQtVersion() # This will fail on Qt 5
gdb.execute("ptype QString::shared_empty", to_string=True)
self.cachedQtVersion = 0x040800
except: except:
try: #self.cachedQtVersion = 0x050000
# This will fail on Qt 5 # Assume Qt 5 until we have a definitive answer.
gdb.execute("ptype QString::shared_empty", to_string=True) return 0x050000
self.cachedQtVersion = 0x040800
except: # Memoize good results.
self.cachedQtVersion = 0x050000 self.qtVersion = lambda: self.cachedQtVersion
return self.cachedQtVersion return self.cachedQtVersion
# Convenience function. # Convenience function.
@@ -1390,8 +1304,9 @@ class Dumper(DumperBase):
def stripNamespaceFromType(self, typeName): def stripNamespaceFromType(self, typeName):
type = stripClassTag(typeName) type = stripClassTag(typeName)
if len(self.ns) > 0 and type.startswith(self.ns): ns = self.qtNamespace()
type = type[len(self.ns):] if len(ns) > 0 and type.startswith(ns):
type = type[len(ns):]
pos = type.find("<") pos = type.find("<")
# FIXME: make it recognize foo<A>::bar<B>::iterator? # FIXME: make it recognize foo<A>::bar<B>::iterator?
while pos != -1: while pos != -1:
@@ -1425,12 +1340,6 @@ class Dumper(DumperBase):
self.putType(type) self.putType(type)
self.putNumChild(0) self.putNumChild(0)
def currentItemFormat(self):
format = self.formats.get(self.currentIName)
if format is None:
format = self.typeformats.get(stripForFormat(str(self.currentType)))
return format
def putSubItem(self, component, value, tryDynamic=True): def putSubItem(self, component, value, tryDynamic=True):
with SubItem(self, component): with SubItem(self, component):
self.putItem(value, tryDynamic) self.putItem(value, tryDynamic)
@@ -1563,8 +1472,6 @@ class Dumper(DumperBase):
self.putNumChild(0) self.putNumChild(0)
return return
global qqDumpers, qqFormats
type = value.type.unqualified() type = value.type.unqualified()
typeName = str(type) typeName = str(type)
tryDynamic &= self.useDynamicType tryDynamic &= self.useDynamicType
@@ -1653,9 +1560,9 @@ class Dumper(DumperBase):
return return
if type.code == TypedefCode: if type.code == TypedefCode:
if typeName in qqDumpers: if typeName in self.qqDumpers:
self.putType(typeName) self.putType(typeName)
qqDumpers[typeName](self, value) self.qqDumpers[typeName](self, value)
return return
type = stripTypedefs(type) type = stripTypedefs(type)
@@ -1708,9 +1615,7 @@ class Dumper(DumperBase):
innerType = type.target() innerType = type.target()
innerTypeName = str(innerType.unqualified()) innerTypeName = str(innerType.unqualified())
format = self.formats.get(self.currentIName) format = self.currentItemFormat(type)
if format is None:
format = self.typeformats.get(stripForFormat(str(type)))
if innerType.code == VoidCode: if innerType.code == VoidCode:
#warn("VOID POINTER: %s" % format) #warn("VOID POINTER: %s" % format)
@@ -1868,9 +1773,7 @@ class Dumper(DumperBase):
self.putItem(expensiveDowncast(value), False) self.putItem(expensiveDowncast(value), False)
return return
format = self.formats.get(self.currentIName) format = self.currentItemFormat(typeName)
if format is None:
format = self.typeformats.get(stripForFormat(typeName))
if self.useFancy and (format is None or format >= 1): if self.useFancy and (format is None or format >= 1):
self.putType(typeName) self.putType(typeName)
@@ -1890,9 +1793,9 @@ class Dumper(DumperBase):
return return
#warn(" STRIPPED: %s" % nsStrippedType) #warn(" STRIPPED: %s" % nsStrippedType)
#warn(" DUMPERS: %s" % qqDumpers) #warn(" DUMPERS: %s" % self.qqDumpers)
#warn(" DUMPERS: %s" % (nsStrippedType in qqDumpers)) #warn(" DUMPERS: %s" % (nsStrippedType in self.qqDumpers))
dumper = qqDumpers.get(nsStrippedType, None) dumper = self.qqDumpers.get(nsStrippedType, None)
if not dumper is None: if not dumper is None:
if tryDynamic: if tryDynamic:
dumper(self, expensiveDowncast(value)) dumper(self, expensiveDowncast(value))
@@ -2031,10 +1934,57 @@ class Dumper(DumperBase):
with Children(self, 1): with Children(self, 1):
self.listAnonymous(value, name, field.type) self.listAnonymous(value, name, field.type)
def registerDumper(self, funcname, function):
try:
#warn("FUNCTION: %s " % funcname)
#funcname = function.func_name
if funcname.startswith("qdump__"):
type = funcname[7:]
self.qqDumpers[type] = function
self.qqFormats[type] = self.qqFormats.get(type, "")
elif funcname.startswith("qform__"):
type = funcname[7:]
formats = ""
try:
formats = function()
except:
pass
self.qqFormats[type] = formats
elif funcname.startswith("qedit__"):
type = funcname[7:]
try:
self.qqEditable[type] = function
except:
pass
except:
pass
def bbsetup(self):
self.qqDumpers = {}
self.qqFormats = {}
self.qqEditable = {}
self.typeCache = {}
module = sys.modules[__name__]
#warn("KEYS: %s " % module.__dict__.keys())
for name in module.__dict__.keys():
#warn("KEY: %s " % name)
#warn("FUNCT: %s " % module.__dict__[name])
self.registerDumper(name, module.__dict__[name])
result = "dumpers=["
for key, value in self.qqFormats.items():
if key in self.qqEditable:
result += '{type="%s",formats="%s",editable="true"},' % (key, value)
else:
result += '{type="%s",formats="%s"},' % (key, value)
result += ']'
return result
def threadname(self, maximalStackDepth): def threadname(self, maximalStackDepth):
e = gdb.selected_frame() e = gdb.selected_frame()
ns = qtNamespace()
out = "" out = ""
ns = self.qtNamespace()
while True: while True:
maximalStackDepth -= 1 maximalStackDepth -= 1
if maximalStackDepth < 0: if maximalStackDepth < 0:
@@ -2087,6 +2037,54 @@ class Dumper(DumperBase):
return out + ']' return out + ']'
def importPlainDumper(self, printer):
name = printer.name.replace("::", "__")
self.qqDumpers[name] = PlainDumper(printer)
self.qqFormats[name] = ""
def importPlainDumpers(self):
for obj in gdb.objfiles():
for printers in obj.pretty_printers + gdb.pretty_printers:
for printer in printers.subprinters:
self.importPlainDumper(printer)
def qtNamespace(self):
# FIXME: This only works when call from inside a Qt function frame.
namespace = ""
try:
str = gdb.execute("ptype QString::Null", to_string=True)
# The result looks like:
# "type = const struct myns::QString::Null {"
# " <no data fields>"
# "}"
pos1 = str.find("struct") + 7
pos2 = str.find("QString::Null")
if pos1 > -1 and pos2 > -1:
namespace = str[pos1:pos2]
self.cachedQtNamespace = namespace
self.ns = lambda: self.cachedQtNamespace
except:
pass
return namespace
def bbedit(self, type, expr, value):
type = b16decode(type)
ns = self.qtNamespace()
if type.startswith(ns):
type = type[len(ns):]
type = type.replace("::", "__")
pos = type.find('<')
if pos != -1:
type = type[0:pos]
expr = b16decode(expr)
value = b16decode(value)
#warn("EDIT: %s %s %s %s: " % (pos, type, expr, value))
if self.qqEditable.has_key(type):
self.qqEditable[type](expr, value)
else:
gdb.execute("set (%s)=%s" % (expr, value))
# Global instance. # Global instance.
theDumper = Dumper() theDumper = Dumper()

View File

@@ -78,27 +78,6 @@ import lldb
qqWatchpointOffset = 10000 qqWatchpointOffset = 10000
def registerDumper(function):
if hasattr(function, 'func_name'):
funcname = function.func_name
if funcname.startswith("qdump__"):
type = funcname[7:]
qqDumpers[type] = function
qqFormats[type] = qqFormats.get(type, "")
elif funcname.startswith("qform__"):
type = funcname[7:]
formats = ""
try:
formats = function()
except:
pass
qqFormats[type] = formats
elif funcname.startswith("qedit__"):
type = funcname[7:]
try:
qqEditable[type] = function
except:
pass
def warn(message): def warn(message):
print('\n\nWARNING="%s",\n' % message.encode("latin1").replace('"', "'")) print('\n\nWARNING="%s",\n' % message.encode("latin1").replace('"', "'"))
@@ -293,7 +272,6 @@ class Dumper(DumperBase):
self.expandedINames = {} self.expandedINames = {}
self.passExceptions = True self.passExceptions = True
self.useLldbDumpers = False self.useLldbDumpers = False
self.ns = ""
self.autoDerefPointers = True self.autoDerefPointers = True
self.useDynamicType = True self.useDynamicType = True
self.useFancy = True self.useFancy = True
@@ -449,10 +427,7 @@ class Dumper(DumperBase):
return typeobj.GetTypeClass() in (lldb.eTypeClassStruct, lldb.eTypeClassClass) return typeobj.GetTypeClass() in (lldb.eTypeClassStruct, lldb.eTypeClassClass)
def qtVersion(self): def qtVersion(self):
global qqVersion self.cachedQtVersion = 0x0
if not qqVersion is None:
return qqVersion
qqVersion = 0x0
coreExpression = re.compile(r"(lib)?Qt5?Core") coreExpression = re.compile(r"(lib)?Qt5?Core")
for n in range(0, self.target.GetNumModules()): for n in range(0, self.target.GetNumModules()):
module = self.target.GetModuleAtIndex(n) module = self.target.GetModuleAtIndex(n)
@@ -461,10 +436,13 @@ class Dumper(DumperBase):
reverseVersion.reverse() reverseVersion.reverse()
shift = 0 shift = 0
for v in reverseVersion: for v in reverseVersion:
qqVersion += v << shift self.cachedQtVersion += v << shift
shift += 8 shift += 8
break break
return qqVersion
# Memoize good results.
self.qtVersion = lambda: self.cachedQtVersion
return self.cachedQtVersion
def intSize(self): def intSize(self):
return 4 return 4
@@ -536,12 +514,6 @@ class Dumper(DumperBase):
def putField(self, name, value): def putField(self, name, value):
self.put('%s="%s",' % (name, value)) self.put('%s="%s",' % (name, value))
def currentItemFormat(self):
format = self.formats.get(self.currentIName)
if format is None:
format = self.typeformats.get(stripForFormat(str(self.currentType)))
return format
def isMovableType(self, type): def isMovableType(self, type):
if type.GetTypeClass() in (lldb.eTypeClassBuiltin, lldb.eTypeClassPointer): if type.GetTypeClass() in (lldb.eTypeClassBuiltin, lldb.eTypeClassPointer):
return True return True
@@ -845,11 +817,16 @@ class Dumper(DumperBase):
self.currentValuePriority = priority self.currentValuePriority = priority
self.currentValueEncoding = encoding self.currentValueEncoding = encoding
def qtNamespace(self):
# FIXME
return ""
def stripNamespaceFromType(self, typeName): def stripNamespaceFromType(self, typeName):
#type = stripClassTag(typeName) #type = stripClassTag(typeName)
type = typeName type = typeName
#if len(self.ns) > 0 and type.startswith(self.ns): #ns = qtNamespace()
# type = type[len(self.ns):] #if len(ns) > 0 and type.startswith(ns):
# type = type[len(ns):]
pos = type.find("<") pos = type.find("<")
# FIXME: make it recognize foo<A>::bar<B>::iterator? # FIXME: make it recognize foo<A>::bar<B>::iterator?
while pos != -1: while pos != -1:
@@ -912,10 +889,10 @@ class Dumper(DumperBase):
# Typedefs # Typedefs
if typeClass == lldb.eTypeClassTypedef: if typeClass == lldb.eTypeClassTypedef:
if typeName in qqDumpers: if typeName in self.qqDumpers:
self.putType(typeName) self.putType(typeName)
self.context = value self.context = value
qqDumpers[typeName](self, value) self.qqDumpers[typeName](self, value)
return return
realType = value.GetType() realType = value.GetType()
if hasattr(realType, 'GetCanonicalType'): if hasattr(realType, 'GetCanonicalType'):
@@ -970,9 +947,7 @@ class Dumper(DumperBase):
innerType = value.GetType().GetPointeeType().unqualified() innerType = value.GetType().GetPointeeType().unqualified()
innerTypeName = str(innerType) innerTypeName = str(innerType)
format = self.formats.get(self.currentIName) format = self.currentItemFormat(type)
if format is None:
format = self.typeformats.get(stripForFormat(str(type)))
if innerTypeName == "void": if innerTypeName == "void":
warn("VOID POINTER: %s" % format) warn("VOID POINTER: %s" % format)
@@ -1130,11 +1105,11 @@ class Dumper(DumperBase):
if self.useFancy: if self.useFancy:
stripped = self.stripNamespaceFromType(typeName).replace("::", "__") stripped = self.stripNamespaceFromType(typeName).replace("::", "__")
#warn("STRIPPED: %s" % stripped) #warn("STRIPPED: %s" % stripped)
#warn("DUMPABLE: %s" % (stripped in qqDumpers)) #warn("DUMPABLE: %s" % (stripped in self.qqDumpers))
if stripped in qqDumpers: if stripped in self.qqDumpers:
self.putType(typeName) self.putType(typeName)
self.context = value self.context = value
qqDumpers[stripped](self, value) self.qqDumpers[stripped](self, value)
return return
# Normal value # Normal value
@@ -1634,13 +1609,34 @@ class Dumper(DumperBase):
self.reportError(error) self.reportError(error)
self.reportVariables() self.reportVariables()
def registerDumper(self, function):
if hasattr(function, 'func_name'):
funcname = function.func_name
if funcname.startswith("qdump__"):
type = funcname[7:]
self.qqDumpers[type] = function
self.qqFormats[type] = self.qqFormats.get(type, "")
elif funcname.startswith("qform__"):
type = funcname[7:]
formats = ""
try:
formats = function()
except:
pass
self.qqFormats[type] = formats
elif funcname.startswith("qedit__"):
type = funcname[7:]
try:
self.qqEditable[type] = function
except:
pass
def importDumpers(self, _ = None): def importDumpers(self, _ = None):
result = lldb.SBCommandReturnObject() result = lldb.SBCommandReturnObject()
interpreter = self.debugger.GetCommandInterpreter() interpreter = self.debugger.GetCommandInterpreter()
global qqDumpers, qqFormats, qqEditable
items = globals() items = globals()
for key in items: for key in items:
registerDumper(items[key]) self.registerDumper(items[key])
def execute(self, args): def execute(self, args):
getattr(self, args['cmd'])(args) getattr(self, args['cmd'])(args)

View File

@@ -94,7 +94,7 @@ def qdump__QAbstractItemModel(d, value):
#format == 2: #format == 2:
# Create a default-constructed QModelIndex on the stack. # Create a default-constructed QModelIndex on the stack.
try: try:
ri = d.makeValue(d.ns + "QModelIndex", "-1, -1, 0, 0") ri = d.makeValue(d.qtNamespace() + "QModelIndex", "-1, -1, 0, 0")
this_ = d.makeExpression(value) this_ = d.makeExpression(value)
ri_ = d.makeExpression(ri) ri_ = d.makeExpression(ri)
rowCount = int(d.parseAndEvaluate("%s.rowCount(%s)" % (this_, ri_))) rowCount = int(d.parseAndEvaluate("%s.rowCount(%s)" % (this_, ri_)))
@@ -147,8 +147,9 @@ def qdump__QModelIndex(d, value):
mm = m.dereference() mm = m.dereference()
mm = mm.cast(mm.type.unqualified()) mm = mm.cast(mm.type.unqualified())
ns = d.qtNamespace()
try: try:
mi = d.makeValue(d.ns + "QModelIndex", "%s,%s,%s,%s" % (r, c, p, m)) mi = d.makeValue(ns + "QModelIndex", "%s,%s,%s,%s" % (r, c, p, m))
mm_ = d.makeExpression(mm) mm_ = d.makeExpression(mm)
mi_ = d.makeExpression(mi) mi_ = d.makeExpression(mi)
rowCount = int(d.parseAndEvaluate("%s.rowCount(%s)" % (mm_, mi_))) rowCount = int(d.parseAndEvaluate("%s.rowCount(%s)" % (mm_, mi_)))
@@ -162,7 +163,7 @@ def qdump__QModelIndex(d, value):
# Access DisplayRole as value # Access DisplayRole as value
val = d.parseAndEvaluate("%s.data(%s, 0)" % (mm_, mi_)) val = d.parseAndEvaluate("%s.data(%s, 0)" % (mm_, mi_))
v = val["d"]["data"]["ptr"] v = val["d"]["data"]["ptr"]
d.putStringValue(d.makeValue(d.ns + 'QString', v)) d.putStringValue(d.makeValue(ns + 'QString', v))
except: except:
d.putValue("(invalid)") d.putValue("(invalid)")
@@ -181,7 +182,7 @@ def qdump__QModelIndex(d, value):
#d.putCallItem("parent", val, "parent") #d.putCallItem("parent", val, "parent")
#with SubItem(d, "model"): #with SubItem(d, "model"):
# d.putValue(m) # d.putValue(m)
# d.putType(d.ns + "QAbstractItemModel*") # d.putType(ns + "QAbstractItemModel*")
# d.putNumChild(1) # d.putNumChild(1)
#gdb.execute("call free($mi)") #gdb.execute("call free($mi)")
@@ -192,7 +193,7 @@ def qdump__QDate(d, value):
d.putValue(jd, JulianDate) d.putValue(jd, JulianDate)
d.putNumChild(1) d.putNumChild(1)
if d.isExpanded(): if d.isExpanded():
qt = d.ns + "Qt::" qt = d.qtNamespace() + "Qt::"
if d.isLldb: if d.isLldb:
qt += "DateFormat::" # FIXME: Bug?... qt += "DateFormat::" # FIXME: Bug?...
# FIXME: This improperly uses complex return values. # FIXME: This improperly uses complex return values.
@@ -213,8 +214,9 @@ def qdump__QTime(d, value):
d.putValue(mds, MillisecondsSinceMidnight) d.putValue(mds, MillisecondsSinceMidnight)
d.putNumChild(1) d.putNumChild(1)
if d.isExpanded(): if d.isExpanded():
qtdate = d.ns + "Qt::" ns = d.qtNamespace()
qttime = d.ns + "Qt::" qtdate = ns + "Qt::"
qttime = ns + "Qt::"
if d.isLldb: if d.isLldb:
qtdate += "DateFormat::" # FIXME: Bug?... qtdate += "DateFormat::" # FIXME: Bug?...
# FIXME: This improperly uses complex return values. # FIXME: This improperly uses complex return values.
@@ -267,8 +269,8 @@ def qdump__QDateTime(d, value):
if d.isExpanded(): if d.isExpanded():
# FIXME: This improperly uses complex return values. # FIXME: This improperly uses complex return values.
with Children(d): with Children(d):
qtdate = d.ns + "Qt::" qtdate = d.qtNamespace() + "Qt::"
qttime = d.ns + "Qt::" qttime = qtdate
if d.isLldb: if d.isLldb:
qtdate += "DateFormat::" # FIXME: Bug?... qtdate += "DateFormat::" # FIXME: Bug?...
qttime += "TimeSpec::" # FIXME: Bug?... qttime += "TimeSpec::" # FIXME: Bug?...
@@ -320,24 +322,25 @@ def qdump__QDir(d, value):
d.putStringValueByAddress(privAddress + dirEntryOffset) d.putStringValueByAddress(privAddress + dirEntryOffset)
if d.isExpanded(): if d.isExpanded():
with Children(d): with Children(d):
ns = d.qtNamespace()
d.call(value, "count") # Fill cache. d.call(value, "count") # Fill cache.
#d.putCallItem("absolutePath", value, "absolutePath") #d.putCallItem("absolutePath", value, "absolutePath")
#d.putCallItem("canonicalPath", value, "canonicalPath") #d.putCallItem("canonicalPath", value, "canonicalPath")
with SubItem(d, "absolutePath"): with SubItem(d, "absolutePath"):
typ = d.lookupType(d.ns + "QString") typ = d.lookupType(ns + "QString")
d.putItem(d.createValue(privAddress + absoluteDirEntryOffset, typ)) d.putItem(d.createValue(privAddress + absoluteDirEntryOffset, typ))
with SubItem(d, "entryInfoList"): with SubItem(d, "entryInfoList"):
typ = d.lookupType(d.ns + "QList<" + d.ns + "QFileInfo>") typ = d.lookupType(ns + "QList<" + ns + "QFileInfo>")
d.putItem(d.createValue(privAddress + fileInfosOffset, typ)) d.putItem(d.createValue(privAddress + fileInfosOffset, typ))
with SubItem(d, "entryList"): with SubItem(d, "entryList"):
typ = d.lookupType(d.ns + "QStringList") typ = d.lookupType(ns + "QStringList")
d.putItem(d.createValue(privAddress + filesOffset, typ)) d.putItem(d.createValue(privAddress + filesOffset, typ))
def qdump__QFile(d, value): def qdump__QFile(d, value):
try: try:
# Try using debug info first. # Try using debug info first.
ptype = d.lookupType(d.ns + "QFilePrivate").pointer() ptype = d.lookupType(d.qtNamespace() + "QFilePrivate").pointer()
d_ptr = value["d_ptr"]["d"] d_ptr = value["d_ptr"]["d"]
fileNameAddress = d.addressOf(d_ptr.cast(ptype).dereference()["fileName"]) fileNameAddress = d.addressOf(d_ptr.cast(ptype).dereference()["fileName"])
d.putNumChild(1) d.putNumChild(1)
@@ -370,7 +373,8 @@ def qdump__QFileInfo(d, value):
d.putStringValueByAddress(filePathAddress) d.putStringValueByAddress(filePathAddress)
d.putNumChild(1) d.putNumChild(1)
if d.isExpanded(): if d.isExpanded():
with Children(d, childType=d.lookupType(d.ns + "QString")): ns = d.qtNamespace()
with Children(d, childType=d.lookupType(ns + "QString")):
d.putCallItem("absolutePath", value, "absolutePath") d.putCallItem("absolutePath", value, "absolutePath")
d.putCallItem("absoluteFilePath", value, "absoluteFilePath") d.putCallItem("absoluteFilePath", value, "absoluteFilePath")
d.putCallItem("canonicalPath", value, "canonicalPath") d.putCallItem("canonicalPath", value, "canonicalPath")
@@ -399,7 +403,7 @@ def qdump__QFileInfo(d, value):
else: else:
with SubItem(d, "permissions"): with SubItem(d, "permissions"):
d.putEmptyValue() d.putEmptyValue()
d.putType(d.ns + "QFile::Permissions") d.putType(ns + "QFile::Permissions")
d.putNumChild(10) d.putNumChild(10)
if d.isExpanded(): if d.isExpanded():
with Children(d, 10): with Children(d, 10):
@@ -793,7 +797,7 @@ def qdump__QLocale(d, value):
#global qqLocalesCount #global qqLocalesCount
#if qqLocalesCount is None: #if qqLocalesCount is None:
# #try: # #try:
# qqLocalesCount = int(value(d.ns + 'locale_data_size')) # qqLocalesCount = int(value(ns + 'locale_data_size'))
# #except: # #except:
# qqLocalesCount = 438 # qqLocalesCount = 438
#try: #try:
@@ -810,15 +814,16 @@ def qdump__QLocale(d, value):
return return
# FIXME: Poke back for variants. # FIXME: Poke back for variants.
if d.isExpanded(): if d.isExpanded():
with Children(d, childType=d.lookupType(d.ns + "QChar"), childNumChild=0): ns = d.qtNamespace()
with Children(d, childType=d.lookupType(ns + "QChar"), childNumChild=0):
d.putCallItem("country", value, "country") d.putCallItem("country", value, "country")
d.putCallItem("language", value, "language") d.putCallItem("language", value, "language")
d.putCallItem("measurementSystem", value, "measurementSystem") d.putCallItem("measurementSystem", value, "measurementSystem")
d.putCallItem("numberOptions", value, "numberOptions") d.putCallItem("numberOptions", value, "numberOptions")
d.putCallItem("timeFormat_(short)", value, d.putCallItem("timeFormat_(short)", value,
"timeFormat", d.ns + "QLocale::ShortFormat") "timeFormat", ns + "QLocale::ShortFormat")
d.putCallItem("timeFormat_(long)", value, d.putCallItem("timeFormat_(long)", value,
"timeFormat", d.ns + "QLocale::LongFormat") "timeFormat", ns + "QLocale::LongFormat")
d.putCallItem("decimalPoint", value, "decimalPoint") d.putCallItem("decimalPoint", value, "decimalPoint")
d.putCallItem("exponential", value, "exponential") d.putCallItem("exponential", value, "exponential")
d.putCallItem("percent", value, "percent") d.putCallItem("percent", value, "percent")
@@ -858,7 +863,7 @@ def qdumpHelper__Qt4_QMap(d, value, forceLong):
# QMapPayloadNode is QMapNode except for the 'forward' member, so # QMapPayloadNode is QMapNode except for the 'forward' member, so
# its size is most likely the offset of the 'forward' member therein. # its size is most likely the offset of the 'forward' member therein.
# Or possibly 2 * sizeof(void *) # Or possibly 2 * sizeof(void *)
nodeType = d.lookupType(d.ns + "QMapNode<%s,%s>" % (keyType, valueType)) nodeType = d.lookupType(d.qtNamespace() + "QMapNode<%s,%s>" % (keyType, valueType))
nodePointerType = nodeType.pointer() nodePointerType = nodeType.pointer()
payloadSize = nodeType.sizeof - 2 * nodePointerType.sizeof payloadSize = nodeType.sizeof - 2 * nodePointerType.sizeof
@@ -976,9 +981,10 @@ def extractCString(table, offset):
def qdump__QObject(d, value): def qdump__QObject(d, value):
d.putQObjectNameValue(value) d.putQObjectNameValue(value)
ns = d.qtNamespace()
try: try:
privateTypeName = d.ns + "QObjectPrivate" privateTypeName = ns + "QObjectPrivate"
privateType = d.lookupType(privateTypeName) privateType = d.lookupType(privateTypeName)
staticMetaObject = value["staticMetaObject"] staticMetaObject = value["staticMetaObject"]
except: except:
@@ -1030,7 +1036,7 @@ def qdump__QObject(d, value):
with Children(d): with Children(d):
# Local data. # Local data.
if privateTypeName != d.ns + "QObjectPrivate": if privateTypeName != ns + "QObjectPrivate":
if not privateType is None: if not privateType is None:
with SubItem(d, "data"): with SubItem(d, "data"):
d.putEmptyValue() d.putEmptyValue()
@@ -1043,7 +1049,7 @@ def qdump__QObject(d, value):
d.putFields(value) d.putFields(value)
# Parent and children. # Parent and children.
if stripClassTag(str(value.type)) == d.ns + "QObject": if stripClassTag(str(value.type)) == ns + "QObject":
d.putSubItem("parent", d_ptr["parent"]) d.putSubItem("parent", d_ptr["parent"])
d.putSubItem("children", d_ptr["children"]) d.putSubItem("children", d_ptr["children"])
@@ -1055,7 +1061,7 @@ def qdump__QObject(d, value):
dynamicPropertyCount = 0 dynamicPropertyCount = 0
else: else:
extraDataType = d.lookupType( extraDataType = d.lookupType(
d.ns + "QObjectPrivate::ExtraData").pointer() ns + "QObjectPrivate::ExtraData").pointer()
extraData = extraData.cast(extraDataType) extraData = extraData.cast(extraDataType)
ed = extraData.dereference() ed = extraData.dereference()
names = ed["propertyNames"] names = ed["propertyNames"]
@@ -1077,7 +1083,7 @@ def qdump__QObject(d, value):
if d.isExpanded(): if d.isExpanded():
# FIXME: Make this global. Don't leak. # FIXME: Make this global. Don't leak.
variant = "'%sQVariant'" % d.ns variant = "'%sQVariant'" % ns
# Avoid malloc symbol clash with QVector # Avoid malloc symbol clash with QVector
gdb.execute("set $d = (%s*)calloc(sizeof(%s), 1)" gdb.execute("set $d = (%s*)calloc(sizeof(%s), 1)"
% (variant, variant)) % (variant, variant))
@@ -1087,11 +1093,11 @@ def qdump__QObject(d, value):
# Dynamic properties. # Dynamic properties.
if dynamicPropertyCount != 0: if dynamicPropertyCount != 0:
dummyType = d.voidPtrType().pointer() dummyType = d.voidPtrType().pointer()
namesType = d.lookupType(d.ns + "QByteArray") namesType = d.lookupType(ns + "QByteArray")
valuesBegin = values["d"]["begin"] valuesBegin = values["d"]["begin"]
valuesEnd = values["d"]["end"] valuesEnd = values["d"]["end"]
valuesArray = values["d"]["array"] valuesArray = values["d"]["array"]
valuesType = d.lookupType(d.ns + "QVariant") valuesType = d.lookupType(ns + "QVariant")
p = namesArray.cast(dummyType) + namesBegin p = namesArray.cast(dummyType) + namesBegin
q = valuesArray.cast(dummyType) + valuesBegin q = valuesArray.cast(dummyType) + valuesBegin
for i in xrange(dynamicPropertyCount): for i in xrange(dynamicPropertyCount):
@@ -1124,9 +1130,9 @@ def qdump__QObject(d, value):
#warn("FLAGS: %s " % flags) #warn("FLAGS: %s " % flags)
#warn("PROPERTY: %s %s " % (propertyType, propertyName)) #warn("PROPERTY: %s %s " % (propertyType, propertyName))
# #exp = '((\'%sQObject\'*)%s)->property("%s")' \ # #exp = '((\'%sQObject\'*)%s)->property("%s")' \
# % (d.ns, value.address, propertyName) # % (ns, value.address, propertyName)
#exp = '"((\'%sQObject\'*)%s)"' % #exp = '"((\'%sQObject\'*)%s)"' %
#(d.ns, value.address,) #(ns, value.address,)
#warn("EXPRESSION: %s" % exp) #warn("EXPRESSION: %s" % exp)
prop = d.call(value, "property", prop = d.call(value, "property",
str(cleanAddress(metaStringData + metaData[offset]))) str(cleanAddress(metaStringData + metaData[offset])))
@@ -1150,10 +1156,10 @@ def qdump__QObject(d, value):
else: else:
# User types. # User types.
# func = "typeToName(('%sQVariant::Type')%d)" # func = "typeToName(('%sQVariant::Type')%d)"
# % (d.ns, variantType) # % (ns, variantType)
# type = str(d.call(value, func)) # type = str(d.call(value, func))
# type = type[type.find('"') + 1 : type.rfind('"')] # type = type[type.find('"') + 1 : type.rfind('"')]
# type = type.replace("Q", d.ns + "Q") # HACK! # type = type.replace("Q", ns + "Q") # HACK!
# data = d.call(value, "constData") # data = d.call(value, "constData")
# tdata = data.cast(d.lookupType(type).pointer()) # tdata = data.cast(d.lookupType(type).pointer())
# .dereference() # .dereference()
@@ -1465,15 +1471,16 @@ def qdump__QRegExp(d, value):
# - QStringList captures (+3ptr +2enum +1bool +3pad?) # - QStringList captures (+3ptr +2enum +1bool +3pad?)
# FIXME: Remove need to call. Needed to warm up cache. # FIXME: Remove need to call. Needed to warm up cache.
d.call(value, "capturedTexts") # create cache d.call(value, "capturedTexts") # create cache
ns = d.qtNamespace()
with SubItem(d, "syntax"): with SubItem(d, "syntax"):
# value["priv"]["engineKey"["capturedCache"] # value["priv"]["engineKey"["capturedCache"]
address = engineKeyAddress + d.ptrSize() address = engineKeyAddress + d.ptrSize()
typ = d.lookupType(d.ns + "QRegExp::PatternSyntax") typ = d.lookupType(ns + "QRegExp::PatternSyntax")
d.putItem(d.createValue(address, typ)) d.putItem(d.createValue(address, typ))
with SubItem(d, "captures"): with SubItem(d, "captures"):
# value["priv"]["capturedCache"] # value["priv"]["capturedCache"]
address = privAddress + 3 * d.ptrSize() + 12 address = privAddress + 3 * d.ptrSize() + 12
typ = d.lookupType(d.ns + "QStringList") typ = d.lookupType(ns + "QStringList")
d.putItem(d.createValue(address, typ)) d.putItem(d.createValue(address, typ))
@@ -1496,7 +1503,8 @@ def qdump__QRegion(d, value):
if d.isExpanded(): if d.isExpanded():
with Children(d): with Children(d):
v = d.ptrSize() v = d.ptrSize()
rectType = d.lookupType(d.ns + "QRect") ns = d.qtNamespace()
rectType = d.lookupType(ns + "QRect")
d.putIntItem("numRects", n) d.putIntItem("numRects", n)
d.putSubItem("extents", d.createValue(pp + 2 * v, rectType)) d.putSubItem("extents", d.createValue(pp + 2 * v, rectType))
d.putSubItem("innerRect", d.createValue(pp + 2 * v + rectType.sizeof, rectType)) d.putSubItem("innerRect", d.createValue(pp + 2 * v + rectType.sizeof, rectType))
@@ -1504,12 +1512,12 @@ def qdump__QRegion(d, value):
# FIXME # FIXME
try: try:
# Can fail if QVector<QRect> debuginfo is missing. # Can fail if QVector<QRect> debuginfo is missing.
vectType = d.lookupType("%sQVector<%sQRect>" % (d.ns, d.ns)) vectType = d.lookupType("%sQVector<%sQRect>" % (ns, ns))
d.putSubItem("rects", d.createValue(pp + v, vectType)) d.putSubItem("rects", d.createValue(pp + v, vectType))
except: except:
with SubItem(d, "rects"): with SubItem(d, "rects"):
d.putItemCount(n) d.putItemCount(n)
d.putType("%sQVector<%sQRect>" % (d.ns, d.ns)) d.putType("%sQVector<%sQRect>" % (ns, ns))
d.putNumChild(0) d.putNumChild(0)
@@ -1761,7 +1769,7 @@ def qdump__QUrl(d, value):
d.putValue(url, Hex4EncodedLittleEndian) d.putValue(url, Hex4EncodedLittleEndian)
d.putNumChild(8) d.putNumChild(8)
if d.isExpanded(): if d.isExpanded():
stringType = d.lookupType(d.ns + "QString") stringType = d.lookupType(d.qtNamespace() + "QString")
with Children(d): with Children(d):
d.putIntItem("port", port) d.putIntItem("port", port)
d.putGenericItem("scheme", stringType, scheme, Hex4EncodedLittleEndian) d.putGenericItem("scheme", stringType, scheme, Hex4EncodedLittleEndian)
@@ -1774,12 +1782,12 @@ def qdump__QUrl(d, value):
def qdumpHelper_QVariant_0(d, data): def qdumpHelper_QVariant_0(d, data):
# QVariant::Invalid # QVariant::Invalid
d.putBetterType("%sQVariant (invalid)" % d.ns) d.putBetterType("%sQVariant (invalid)" % d.qtNamespace())
d.putValue("(invalid)") d.putValue("(invalid)")
def qdumpHelper_QVariant_1(d, data): def qdumpHelper_QVariant_1(d, data):
# QVariant::Bool # QVariant::Bool
d.putBetterType("%sQVariant (bool)" % d.ns) d.putBetterType("%sQVariant (bool)" % d.qtNamespace())
if int(data["b"]): if int(data["b"]):
d.putValue("true") d.putValue("true")
else: else:
@@ -1787,27 +1795,27 @@ def qdumpHelper_QVariant_1(d, data):
def qdumpHelper_QVariant_2(d, data): def qdumpHelper_QVariant_2(d, data):
# QVariant::Int # QVariant::Int
d.putBetterType("%sQVariant (int)" % d.ns) d.putBetterType("%sQVariant (int)" % d.qtNamespace())
d.putValue(int(data["i"])) d.putValue(int(data["i"]))
def qdumpHelper_QVariant_3(d, data): def qdumpHelper_QVariant_3(d, data):
# uint # uint
d.putBetterType("%sQVariant (uint)" % d.ns) d.putBetterType("%sQVariant (uint)" % d.qtNamespace())
d.putValue(int(data["u"])) d.putValue(int(data["u"]))
def qdumpHelper_QVariant_4(d, data): def qdumpHelper_QVariant_4(d, data):
# qlonglong # qlonglong
d.putBetterType("%sQVariant (qlonglong)" % d.ns) d.putBetterType("%sQVariant (qlonglong)" % d.qtNamespace())
d.putValue(int(data["ll"])) d.putValue(int(data["ll"]))
def qdumpHelper_QVariant_5(d, data): def qdumpHelper_QVariant_5(d, data):
# qulonglong # qulonglong
d.putBetterType("%sQVariant (qulonglong)" % d.ns) d.putBetterType("%sQVariant (qulonglong)" % d.qtNamespace())
d.putValue(int(data["ull"])) d.putValue(int(data["ull"]))
def qdumpHelper_QVariant_6(d, data): def qdumpHelper_QVariant_6(d, data):
# QVariant::Double # QVariant::Double
d.putBetterType("%sQVariant (double)" % d.ns) d.putBetterType("%sQVariant (double)" % d.qtNamespace())
d.putValue(float(data["d"])) d.putValue(float(data["d"]))
qdumpHelper_QVariants_A = [ qdumpHelper_QVariants_A = [
@@ -1893,7 +1901,7 @@ def qdumpHelper__QVariant(d, value):
else: else:
innert = qdumpHelper_QVariants_C[variantType - 64] innert = qdumpHelper_QVariants_C[variantType - 64]
inner = d.ns + innert inner = d.qtNamespace() + innert
innerType = d.lookupType(inner) innerType = d.lookupType(inner)
sizePD = 8 # sizeof(QVariant::Private::Data) sizePD = 8 # sizeof(QVariant::Private::Data)
@@ -1908,7 +1916,7 @@ def qdumpHelper__QVariant(d, value):
d.putEmptyValue(-99) d.putEmptyValue(-99)
d.putItem(val) d.putItem(val)
d.putBetterType("%sQVariant (%s)" % (d.ns, innert)) d.putBetterType("%sQVariant (%s)" % (d.qtNamespace(), innert))
return (None, innert, True) return (None, innert, True)
@@ -1922,14 +1930,15 @@ def qdump__QVariant(d, value):
# User types. # User types.
d_ptr = value["d"] d_ptr = value["d"]
typeCode = int(d_ptr["type"]) typeCode = int(d_ptr["type"])
ns = d.qtNamespace()
try: try:
exp = "((const char *(*)(int))%sQMetaType::typeName)(%d)" % (d.ns, typeCode) exp = "((const char *(*)(int))%sQMetaType::typeName)(%d)" % (ns, typeCode)
type = str(d.parseAndEvaluate(exp)) type = str(d.parseAndEvaluate(exp))
except: except:
exp = "%sQMetaType::typeName(%d)" % (d.ns, typeCode) exp = "%sQMetaType::typeName(%d)" % (ns, typeCode)
type = str(d.parseAndEvaluate(exp)) type = str(d.parseAndEvaluate(exp))
type = type[type.find('"') + 1 : type.rfind('"')] type = type[type.find('"') + 1 : type.rfind('"')]
type = type.replace("Q", d.ns + "Q") # HACK! type = type.replace("Q", ns + "Q") # HACK!
type = type.replace("uint", "unsigned int") # HACK! type = type.replace("uint", "unsigned int") # HACK!
type = type.replace("COMMA", ",") # HACK! type = type.replace("COMMA", ",") # HACK!
type = type.replace(" ,", ",") # Lldb type = type.replace(" ,", ",") # Lldb
@@ -1937,7 +1946,7 @@ def qdump__QVariant(d, value):
data = d.call(value, "constData") data = d.call(value, "constData")
#warn("DATA: %s" % data) #warn("DATA: %s" % data)
d.putEmptyValue(-99) d.putEmptyValue(-99)
d.putType("%sQVariant (%s)" % (d.ns, type)) d.putType("%sQVariant (%s)" % (ns, type))
d.putNumChild(1) d.putNumChild(1)
tdata = data.cast(d.lookupType(type).pointer()).dereference() tdata = data.cast(d.lookupType(type).pointer()).dereference()
if d.isExpanded(): if d.isExpanded():
@@ -2075,7 +2084,7 @@ def qdump__QTJSC__JSValue(d, value):
try: try:
# FIXME: This might not always be a variant. # FIXME: This might not always be a variant.
delegateType = d.lookupType(d.ns + "QScript::QVariantDelegate").pointer() delegateType = d.lookupType(d.qtNamespace() + "QScript::QVariantDelegate").pointer()
delegate = scriptObject["d"]["delegate"].cast(delegateType) delegate = scriptObject["d"]["delegate"].cast(delegateType)
#d.putSubItem("delegate", delegate) #d.putSubItem("delegate", delegate)
variant = delegate["m_value"] variant = delegate["m_value"]
@@ -2096,21 +2105,22 @@ def qdump__QScriptValue(d, value):
# type QScriptValuePrivate::Type: { JavaScriptCore, Number, String } # type QScriptValuePrivate::Type: { JavaScriptCore, Number, String }
#d.putEmptyValue() #d.putEmptyValue()
dd = value["d_ptr"]["d"] dd = value["d_ptr"]["d"]
ns = d.qtNamespace()
if d.isNull(dd): if d.isNull(dd):
d.putValue("(invalid)") d.putValue("(invalid)")
d.putNumChild(0) d.putNumChild(0)
return return
if int(dd["type"]) == 1: # Number if int(dd["type"]) == 1: # Number
d.putValue(dd["numberValue"]) d.putValue(dd["numberValue"])
d.putType("%sQScriptValue (Number)" % d.ns) d.putType("%sQScriptValue (Number)" % ns)
d.putNumChild(0) d.putNumChild(0)
return return
if int(dd["type"]) == 2: # String if int(dd["type"]) == 2: # String
d.putStringValue(dd["stringValue"]) d.putStringValue(dd["stringValue"])
d.putType("%sQScriptValue (String)" % d.ns) d.putType("%sQScriptValue (String)" % ns)
return return
d.putType("%sQScriptValue (JSCoreValue)" % d.ns) d.putType("%sQScriptValue (JSCoreValue)" % ns)
x = dd["jscValue"]["u"] x = dd["jscValue"]["u"]
tag = x["asBits"]["tag"] tag = x["asBits"]["tag"]
payload = x["asBits"]["payload"] payload = x["asBits"]["payload"]
@@ -2144,11 +2154,11 @@ def qdump__QScriptValue(d, value):
try: try:
# This might already fail for "native" payloads. # This might already fail for "native" payloads.
scriptObjectType = d.lookupType(d.ns + "QScriptObject").pointer() scriptObjectType = d.lookupType(ns + "QScriptObject").pointer()
scriptObject = payload.cast(scriptObjectType) scriptObject = payload.cast(scriptObjectType)
# FIXME: This might not always be a variant. # FIXME: This might not always be a variant.
delegateType = d.lookupType(d.ns + "QScript::QVariantDelegate").pointer() delegateType = d.lookupType(ns + "QScript::QVariantDelegate").pointer()
delegate = scriptObject["d"]["delegate"].cast(delegateType) delegate = scriptObject["d"]["delegate"].cast(delegateType)
#d.putSubItem("delegate", delegate) #d.putSubItem("delegate", delegate)
@@ -2156,7 +2166,7 @@ def qdump__QScriptValue(d, value):
#d.putSubItem("variant", variant) #d.putSubItem("variant", variant)
t = qdump__QVariant(d, variant) t = qdump__QVariant(d, variant)
# Override the "QVariant (foo)" output # Override the "QVariant (foo)" output
d.putBetterType("%sQScriptValue (%s)" % (d.ns, t)) d.putBetterType("%sQScriptValue (%s)" % (ns, t))
if t != "JSCoreValue": if t != "JSCoreValue":
return return
except: except:

View File

@@ -321,7 +321,7 @@ def qdump__std__stringHelper1(d, value, charSize):
qdump_stringHelper(d, sizePtr, size * charSize, charSize) qdump_stringHelper(d, sizePtr, size * charSize, charSize)
def qdump_stringHelper(d, data, size, charSize): def qdump_stringHelper(d, data, size, charSize):
cutoff = min(size, qqStringCutOff) cutoff = min(size, d.stringCutOff)
mem = d.readMemory(data, cutoff) mem = d.readMemory(data, cutoff)
if charSize == 1: if charSize == 1:
encodingType = Hex2EncodedLatin1 encodingType = Hex2EncodedLatin1

View File

@@ -910,7 +910,7 @@ void tst_Dumpers::dumper()
"python from gdbbridge import *\n" "python from gdbbridge import *\n"
"run " + nograb + "\n" "run " + nograb + "\n"
"up\n" "up\n"
"python print('@%sS@%s@' % ('N', qtNamespace()))\n" "python print('@%sS@%s@' % ('N', theDumper.qtNamespace()))\n"
"bb options:fancy,autoderef,dyntype,pe vars: expanded:" + expanded + " typeformats:\n"; "bb options:fancy,autoderef,dyntype,pe vars: expanded:" + expanded + " typeformats:\n";
} else { } else {
cmds += "run\n"; cmds += "run\n";