diff --git a/share/qtcreator/debugger/dumper.py b/share/qtcreator/debugger/dumper.py index f6f64c65b011a74bc3159047c59f9380b829f9dd..2a2135f8a5695e6c81f966937ab437572eb0fed9 100644 --- a/share/qtcreator/debugger/dumper.py +++ b/share/qtcreator/debugger/dumper.py @@ -41,44 +41,6 @@ else: verbosity = 0 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(): fileName = "/usr/bin/gnuplot" return os.path.isfile(fileName) and os.access(fileName, os.X_OK) @@ -261,6 +223,44 @@ class DumperBase: self.isGdb = 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): return self.ptrSize() == 4 @@ -268,7 +268,7 @@ class DumperBase: if limit is None: return size if limit == 0: - return min(size, qqStringCutOff) + return min(size, self.stringCutOff) return min(size, limit) def byteArrayDataHelper(self, addr): @@ -372,10 +372,11 @@ class DumperBase: return self.putValue(self.encodeString(value), Hex4EncodedLittleEndian) 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('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('keyencoded="%s",' % Hex2EncodedLatin1) else: @@ -416,9 +417,9 @@ class DumperBase: def encodeCArray(self, p, innerType, suffix): t = self.lookupType(innerType) p = p.cast(t.pointer()) - limit = self.findFirstZero(p, qqStringCutOff) + limit = self.findFirstZero(p, self.stringCutOff) s = self.readMemory(p, limit * t.sizeof) - if limit > qqStringCutOff: + if limit > self.stringCutOff: s += suffix return s @@ -503,6 +504,14 @@ class DumperBase: 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): if addr is None: diff --git a/share/qtcreator/debugger/gdbbridge.py b/share/qtcreator/debugger/gdbbridge.py index 8a81f8742a9af2ebfc53b649e28fce5046c3c090..5bb9d013ba4904d9e3e4023664c875d7342206a0 100644 --- a/share/qtcreator/debugger/gdbbridge.py +++ b/share/qtcreator/debugger/gdbbridge.py @@ -298,57 +298,9 @@ class ScanStackCommand(gdb.Command): 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 = ''): - global qqDumpers, qqFormats, qqEditable, typeCache - 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 + print(theDumper.bbsetup()) registerCommand("bbsetup", bbsetup) @@ -377,18 +329,8 @@ class PlainDumper: for child in children: 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): - return - for obj in gdb.objfiles(): - for printers in obj.pretty_printers + gdb.pretty_printers: - for printer in printers.subprinters: - importPlainDumper(printer) + theDumper.importPlainDumpers() registerCommand("importPlainDumpers", importPlainDumpers) @@ -651,27 +593,6 @@ def value(expr): 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): type = type.unqualified() @@ -698,23 +619,8 @@ class LocalItem: ####################################################################### def bbedit(args): - global qqEditable - (type, expr, value) = 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)) + #(type, expr, value) = args.split(",") + theDumper.bbedit(args.split(",")) registerCommand("bbedit", bbedit) @@ -781,7 +687,9 @@ class Dumper(DumperBase): # These values will be kept between calls to 'run'. self.isGdb = True self.childEventAddress = None - self.cachedQtVersion = None + + # Later set, or not set: + #self.cachedQtVersion def run(self, args): self.output = [] @@ -841,9 +749,7 @@ class Dumper(DumperBase): self.partialUpdate = "partial" in options self.tooltipOnly = "tooltiponly" in options self.noLocals = "nolocals" in options - self.ns = qtNamespace() - - #warn("NAMESPACE: '%s'" % self.ns) + #warn("NAMESPACE: '%s'" % self.qtNamespace()) #warn("VARIABLES: %s" % varList) #warn("EXPANDED INAMES: %s" % self.expandedINames) #warn("WATCHERS: %s" % watchers) @@ -1209,10 +1115,14 @@ class Dumper(DumperBase): def selectedInferior(self): try: # gdb.Inferior is new in gdb 7.2 - return gdb.selected_inferior() + self.cachedInferior = gdb.selected_inferior() except: # 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): mem = self.selectedInferior().read_memory(addr, size) @@ -1289,16 +1199,20 @@ class Dumper(DumperBase): return xrange(min(toInteger(self.currentMaxNumChild), toInteger(self.currentNumChild))) def qtVersion(self): - if self.cachedQtVersion is None: + try: + self.cachedQtVersion = extractQtVersion() + except: try: - self.cachedQtVersion = extractQtVersion() + # This will fail on Qt 5 + gdb.execute("ptype QString::shared_empty", to_string=True) + self.cachedQtVersion = 0x040800 except: - try: - # This will fail on Qt 5 - gdb.execute("ptype QString::shared_empty", to_string=True) - self.cachedQtVersion = 0x040800 - except: - self.cachedQtVersion = 0x050000 + #self.cachedQtVersion = 0x050000 + # Assume Qt 5 until we have a definitive answer. + return 0x050000 + + # Memoize good results. + self.qtVersion = lambda: self.cachedQtVersion return self.cachedQtVersion # Convenience function. @@ -1390,8 +1304,9 @@ class Dumper(DumperBase): def stripNamespaceFromType(self, typeName): type = stripClassTag(typeName) - if len(self.ns) > 0 and type.startswith(self.ns): - type = type[len(self.ns):] + ns = self.qtNamespace() + if len(ns) > 0 and type.startswith(ns): + type = type[len(ns):] pos = type.find("<") # FIXME: make it recognize foo<A>::bar<B>::iterator? while pos != -1: @@ -1425,12 +1340,6 @@ class Dumper(DumperBase): self.putType(type) 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): with SubItem(self, component): self.putItem(value, tryDynamic) @@ -1563,8 +1472,6 @@ class Dumper(DumperBase): self.putNumChild(0) return - global qqDumpers, qqFormats - type = value.type.unqualified() typeName = str(type) tryDynamic &= self.useDynamicType @@ -1653,9 +1560,9 @@ class Dumper(DumperBase): return if type.code == TypedefCode: - if typeName in qqDumpers: + if typeName in self.qqDumpers: self.putType(typeName) - qqDumpers[typeName](self, value) + self.qqDumpers[typeName](self, value) return type = stripTypedefs(type) @@ -1708,9 +1615,7 @@ class Dumper(DumperBase): innerType = type.target() innerTypeName = str(innerType.unqualified()) - format = self.formats.get(self.currentIName) - if format is None: - format = self.typeformats.get(stripForFormat(str(type))) + format = self.currentItemFormat(type) if innerType.code == VoidCode: #warn("VOID POINTER: %s" % format) @@ -1868,9 +1773,7 @@ class Dumper(DumperBase): self.putItem(expensiveDowncast(value), False) return - format = self.formats.get(self.currentIName) - if format is None: - format = self.typeformats.get(stripForFormat(typeName)) + format = self.currentItemFormat(typeName) if self.useFancy and (format is None or format >= 1): self.putType(typeName) @@ -1890,9 +1793,9 @@ class Dumper(DumperBase): return #warn(" STRIPPED: %s" % nsStrippedType) - #warn(" DUMPERS: %s" % qqDumpers) - #warn(" DUMPERS: %s" % (nsStrippedType in qqDumpers)) - dumper = qqDumpers.get(nsStrippedType, None) + #warn(" DUMPERS: %s" % self.qqDumpers) + #warn(" DUMPERS: %s" % (nsStrippedType in self.qqDumpers)) + dumper = self.qqDumpers.get(nsStrippedType, None) if not dumper is None: if tryDynamic: dumper(self, expensiveDowncast(value)) @@ -2031,10 +1934,57 @@ class Dumper(DumperBase): with Children(self, 1): 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): e = gdb.selected_frame() - ns = qtNamespace() out = "" + ns = self.qtNamespace() while True: maximalStackDepth -= 1 if maximalStackDepth < 0: @@ -2087,6 +2037,54 @@ class Dumper(DumperBase): 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. theDumper = Dumper() diff --git a/share/qtcreator/debugger/lldbbridge.py b/share/qtcreator/debugger/lldbbridge.py index 9fa7887787900c64d3c0a00c1ebc9edfb023c3b5..f68705be857176eee3001589ac6ea865ddd01d3f 100644 --- a/share/qtcreator/debugger/lldbbridge.py +++ b/share/qtcreator/debugger/lldbbridge.py @@ -78,27 +78,6 @@ import lldb 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): print('\n\nWARNING="%s",\n' % message.encode("latin1").replace('"', "'")) @@ -293,7 +272,6 @@ class Dumper(DumperBase): self.expandedINames = {} self.passExceptions = True self.useLldbDumpers = False - self.ns = "" self.autoDerefPointers = True self.useDynamicType = True self.useFancy = True @@ -449,10 +427,7 @@ class Dumper(DumperBase): return typeobj.GetTypeClass() in (lldb.eTypeClassStruct, lldb.eTypeClassClass) def qtVersion(self): - global qqVersion - if not qqVersion is None: - return qqVersion - qqVersion = 0x0 + self.cachedQtVersion = 0x0 coreExpression = re.compile(r"(lib)?Qt5?Core") for n in range(0, self.target.GetNumModules()): module = self.target.GetModuleAtIndex(n) @@ -461,10 +436,13 @@ class Dumper(DumperBase): reverseVersion.reverse() shift = 0 for v in reverseVersion: - qqVersion += v << shift + self.cachedQtVersion += v << shift shift += 8 break - return qqVersion + + # Memoize good results. + self.qtVersion = lambda: self.cachedQtVersion + return self.cachedQtVersion def intSize(self): return 4 @@ -536,12 +514,6 @@ class Dumper(DumperBase): def putField(self, 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): if type.GetTypeClass() in (lldb.eTypeClassBuiltin, lldb.eTypeClassPointer): return True @@ -845,11 +817,16 @@ class Dumper(DumperBase): self.currentValuePriority = priority self.currentValueEncoding = encoding + def qtNamespace(self): + # FIXME + return "" + def stripNamespaceFromType(self, typeName): #type = stripClassTag(typeName) type = typeName - #if len(self.ns) > 0 and type.startswith(self.ns): - # type = type[len(self.ns):] + #ns = qtNamespace() + #if len(ns) > 0 and type.startswith(ns): + # type = type[len(ns):] pos = type.find("<") # FIXME: make it recognize foo<A>::bar<B>::iterator? while pos != -1: @@ -912,10 +889,10 @@ class Dumper(DumperBase): # Typedefs if typeClass == lldb.eTypeClassTypedef: - if typeName in qqDumpers: + if typeName in self.qqDumpers: self.putType(typeName) self.context = value - qqDumpers[typeName](self, value) + self.qqDumpers[typeName](self, value) return realType = value.GetType() if hasattr(realType, 'GetCanonicalType'): @@ -970,9 +947,7 @@ class Dumper(DumperBase): innerType = value.GetType().GetPointeeType().unqualified() innerTypeName = str(innerType) - format = self.formats.get(self.currentIName) - if format is None: - format = self.typeformats.get(stripForFormat(str(type))) + format = self.currentItemFormat(type) if innerTypeName == "void": warn("VOID POINTER: %s" % format) @@ -1130,11 +1105,11 @@ class Dumper(DumperBase): if self.useFancy: stripped = self.stripNamespaceFromType(typeName).replace("::", "__") #warn("STRIPPED: %s" % stripped) - #warn("DUMPABLE: %s" % (stripped in qqDumpers)) - if stripped in qqDumpers: + #warn("DUMPABLE: %s" % (stripped in self.qqDumpers)) + if stripped in self.qqDumpers: self.putType(typeName) self.context = value - qqDumpers[stripped](self, value) + self.qqDumpers[stripped](self, value) return # Normal value @@ -1634,13 +1609,34 @@ class Dumper(DumperBase): self.reportError(error) 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): result = lldb.SBCommandReturnObject() interpreter = self.debugger.GetCommandInterpreter() - global qqDumpers, qqFormats, qqEditable items = globals() for key in items: - registerDumper(items[key]) + self.registerDumper(items[key]) def execute(self, args): getattr(self, args['cmd'])(args) diff --git a/share/qtcreator/debugger/qttypes.py b/share/qtcreator/debugger/qttypes.py index 8874c69aa69ad4a3d3e1607f748730914efdbb3b..ea85005adedd1caad04ddf5ef8920461261d3f25 100644 --- a/share/qtcreator/debugger/qttypes.py +++ b/share/qtcreator/debugger/qttypes.py @@ -94,7 +94,7 @@ def qdump__QAbstractItemModel(d, value): #format == 2: # Create a default-constructed QModelIndex on the stack. 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) ri_ = d.makeExpression(ri) rowCount = int(d.parseAndEvaluate("%s.rowCount(%s)" % (this_, ri_))) @@ -147,8 +147,9 @@ def qdump__QModelIndex(d, value): mm = m.dereference() mm = mm.cast(mm.type.unqualified()) + ns = d.qtNamespace() 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) mi_ = d.makeExpression(mi) rowCount = int(d.parseAndEvaluate("%s.rowCount(%s)" % (mm_, mi_))) @@ -162,7 +163,7 @@ def qdump__QModelIndex(d, value): # Access DisplayRole as value val = d.parseAndEvaluate("%s.data(%s, 0)" % (mm_, mi_)) v = val["d"]["data"]["ptr"] - d.putStringValue(d.makeValue(d.ns + 'QString', v)) + d.putStringValue(d.makeValue(ns + 'QString', v)) except: d.putValue("(invalid)") @@ -181,7 +182,7 @@ def qdump__QModelIndex(d, value): #d.putCallItem("parent", val, "parent") #with SubItem(d, "model"): # d.putValue(m) - # d.putType(d.ns + "QAbstractItemModel*") + # d.putType(ns + "QAbstractItemModel*") # d.putNumChild(1) #gdb.execute("call free($mi)") @@ -192,7 +193,7 @@ def qdump__QDate(d, value): d.putValue(jd, JulianDate) d.putNumChild(1) if d.isExpanded(): - qt = d.ns + "Qt::" + qt = d.qtNamespace() + "Qt::" if d.isLldb: qt += "DateFormat::" # FIXME: Bug?... # FIXME: This improperly uses complex return values. @@ -213,8 +214,9 @@ def qdump__QTime(d, value): d.putValue(mds, MillisecondsSinceMidnight) d.putNumChild(1) if d.isExpanded(): - qtdate = d.ns + "Qt::" - qttime = d.ns + "Qt::" + ns = d.qtNamespace() + qtdate = ns + "Qt::" + qttime = ns + "Qt::" if d.isLldb: qtdate += "DateFormat::" # FIXME: Bug?... # FIXME: This improperly uses complex return values. @@ -267,8 +269,8 @@ def qdump__QDateTime(d, value): if d.isExpanded(): # FIXME: This improperly uses complex return values. with Children(d): - qtdate = d.ns + "Qt::" - qttime = d.ns + "Qt::" + qtdate = d.qtNamespace() + "Qt::" + qttime = qtdate if d.isLldb: qtdate += "DateFormat::" # FIXME: Bug?... qttime += "TimeSpec::" # FIXME: Bug?... @@ -320,24 +322,25 @@ def qdump__QDir(d, value): d.putStringValueByAddress(privAddress + dirEntryOffset) if d.isExpanded(): with Children(d): + ns = d.qtNamespace() d.call(value, "count") # Fill cache. #d.putCallItem("absolutePath", value, "absolutePath") #d.putCallItem("canonicalPath", value, "canonicalPath") with SubItem(d, "absolutePath"): - typ = d.lookupType(d.ns + "QString") + typ = d.lookupType(ns + "QString") d.putItem(d.createValue(privAddress + absoluteDirEntryOffset, typ)) 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)) with SubItem(d, "entryList"): - typ = d.lookupType(d.ns + "QStringList") + typ = d.lookupType(ns + "QStringList") d.putItem(d.createValue(privAddress + filesOffset, typ)) def qdump__QFile(d, value): try: # 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"] fileNameAddress = d.addressOf(d_ptr.cast(ptype).dereference()["fileName"]) d.putNumChild(1) @@ -370,7 +373,8 @@ def qdump__QFileInfo(d, value): d.putStringValueByAddress(filePathAddress) d.putNumChild(1) 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("absoluteFilePath", value, "absoluteFilePath") d.putCallItem("canonicalPath", value, "canonicalPath") @@ -399,7 +403,7 @@ def qdump__QFileInfo(d, value): else: with SubItem(d, "permissions"): d.putEmptyValue() - d.putType(d.ns + "QFile::Permissions") + d.putType(ns + "QFile::Permissions") d.putNumChild(10) if d.isExpanded(): with Children(d, 10): @@ -793,7 +797,7 @@ def qdump__QLocale(d, value): #global qqLocalesCount #if qqLocalesCount is None: # #try: - # qqLocalesCount = int(value(d.ns + 'locale_data_size')) + # qqLocalesCount = int(value(ns + 'locale_data_size')) # #except: # qqLocalesCount = 438 #try: @@ -810,15 +814,16 @@ def qdump__QLocale(d, value): return # FIXME: Poke back for variants. 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("language", value, "language") d.putCallItem("measurementSystem", value, "measurementSystem") d.putCallItem("numberOptions", value, "numberOptions") d.putCallItem("timeFormat_(short)", value, - "timeFormat", d.ns + "QLocale::ShortFormat") + "timeFormat", ns + "QLocale::ShortFormat") d.putCallItem("timeFormat_(long)", value, - "timeFormat", d.ns + "QLocale::LongFormat") + "timeFormat", ns + "QLocale::LongFormat") d.putCallItem("decimalPoint", value, "decimalPoint") d.putCallItem("exponential", value, "exponential") 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 # its size is most likely the offset of the 'forward' member therein. # 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() payloadSize = nodeType.sizeof - 2 * nodePointerType.sizeof @@ -976,9 +981,10 @@ def extractCString(table, offset): def qdump__QObject(d, value): d.putQObjectNameValue(value) + ns = d.qtNamespace() try: - privateTypeName = d.ns + "QObjectPrivate" + privateTypeName = ns + "QObjectPrivate" privateType = d.lookupType(privateTypeName) staticMetaObject = value["staticMetaObject"] except: @@ -1030,7 +1036,7 @@ def qdump__QObject(d, value): with Children(d): # Local data. - if privateTypeName != d.ns + "QObjectPrivate": + if privateTypeName != ns + "QObjectPrivate": if not privateType is None: with SubItem(d, "data"): d.putEmptyValue() @@ -1043,7 +1049,7 @@ def qdump__QObject(d, value): d.putFields(value) # 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("children", d_ptr["children"]) @@ -1055,7 +1061,7 @@ def qdump__QObject(d, value): dynamicPropertyCount = 0 else: extraDataType = d.lookupType( - d.ns + "QObjectPrivate::ExtraData").pointer() + ns + "QObjectPrivate::ExtraData").pointer() extraData = extraData.cast(extraDataType) ed = extraData.dereference() names = ed["propertyNames"] @@ -1077,7 +1083,7 @@ def qdump__QObject(d, value): if d.isExpanded(): # FIXME: Make this global. Don't leak. - variant = "'%sQVariant'" % d.ns + variant = "'%sQVariant'" % ns # Avoid malloc symbol clash with QVector gdb.execute("set $d = (%s*)calloc(sizeof(%s), 1)" % (variant, variant)) @@ -1087,11 +1093,11 @@ def qdump__QObject(d, value): # Dynamic properties. if dynamicPropertyCount != 0: dummyType = d.voidPtrType().pointer() - namesType = d.lookupType(d.ns + "QByteArray") + namesType = d.lookupType(ns + "QByteArray") valuesBegin = values["d"]["begin"] valuesEnd = values["d"]["end"] valuesArray = values["d"]["array"] - valuesType = d.lookupType(d.ns + "QVariant") + valuesType = d.lookupType(ns + "QVariant") p = namesArray.cast(dummyType) + namesBegin q = valuesArray.cast(dummyType) + valuesBegin for i in xrange(dynamicPropertyCount): @@ -1124,9 +1130,9 @@ def qdump__QObject(d, value): #warn("FLAGS: %s " % flags) #warn("PROPERTY: %s %s " % (propertyType, propertyName)) # #exp = '((\'%sQObject\'*)%s)->property("%s")' \ - # % (d.ns, value.address, propertyName) + # % (ns, value.address, propertyName) #exp = '"((\'%sQObject\'*)%s)"' % - #(d.ns, value.address,) + #(ns, value.address,) #warn("EXPRESSION: %s" % exp) prop = d.call(value, "property", str(cleanAddress(metaStringData + metaData[offset]))) @@ -1150,10 +1156,10 @@ def qdump__QObject(d, value): else: # User types. # func = "typeToName(('%sQVariant::Type')%d)" - # % (d.ns, variantType) + # % (ns, variantType) # type = str(d.call(value, func)) # 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") # tdata = data.cast(d.lookupType(type).pointer()) # .dereference() @@ -1465,15 +1471,16 @@ def qdump__QRegExp(d, value): # - QStringList captures (+3ptr +2enum +1bool +3pad?) # FIXME: Remove need to call. Needed to warm up cache. d.call(value, "capturedTexts") # create cache + ns = d.qtNamespace() with SubItem(d, "syntax"): # value["priv"]["engineKey"["capturedCache"] address = engineKeyAddress + d.ptrSize() - typ = d.lookupType(d.ns + "QRegExp::PatternSyntax") + typ = d.lookupType(ns + "QRegExp::PatternSyntax") d.putItem(d.createValue(address, typ)) with SubItem(d, "captures"): # value["priv"]["capturedCache"] address = privAddress + 3 * d.ptrSize() + 12 - typ = d.lookupType(d.ns + "QStringList") + typ = d.lookupType(ns + "QStringList") d.putItem(d.createValue(address, typ)) @@ -1496,7 +1503,8 @@ def qdump__QRegion(d, value): if d.isExpanded(): with Children(d): v = d.ptrSize() - rectType = d.lookupType(d.ns + "QRect") + ns = d.qtNamespace() + rectType = d.lookupType(ns + "QRect") d.putIntItem("numRects", n) d.putSubItem("extents", d.createValue(pp + 2 * v, rectType)) d.putSubItem("innerRect", d.createValue(pp + 2 * v + rectType.sizeof, rectType)) @@ -1504,12 +1512,12 @@ def qdump__QRegion(d, value): # FIXME try: # 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)) except: with SubItem(d, "rects"): d.putItemCount(n) - d.putType("%sQVector<%sQRect>" % (d.ns, d.ns)) + d.putType("%sQVector<%sQRect>" % (ns, ns)) d.putNumChild(0) @@ -1761,7 +1769,7 @@ def qdump__QUrl(d, value): d.putValue(url, Hex4EncodedLittleEndian) d.putNumChild(8) if d.isExpanded(): - stringType = d.lookupType(d.ns + "QString") + stringType = d.lookupType(d.qtNamespace() + "QString") with Children(d): d.putIntItem("port", port) d.putGenericItem("scheme", stringType, scheme, Hex4EncodedLittleEndian) @@ -1774,12 +1782,12 @@ def qdump__QUrl(d, value): def qdumpHelper_QVariant_0(d, data): # QVariant::Invalid - d.putBetterType("%sQVariant (invalid)" % d.ns) + d.putBetterType("%sQVariant (invalid)" % d.qtNamespace()) d.putValue("(invalid)") def qdumpHelper_QVariant_1(d, data): # QVariant::Bool - d.putBetterType("%sQVariant (bool)" % d.ns) + d.putBetterType("%sQVariant (bool)" % d.qtNamespace()) if int(data["b"]): d.putValue("true") else: @@ -1787,27 +1795,27 @@ def qdumpHelper_QVariant_1(d, data): def qdumpHelper_QVariant_2(d, data): # QVariant::Int - d.putBetterType("%sQVariant (int)" % d.ns) + d.putBetterType("%sQVariant (int)" % d.qtNamespace()) d.putValue(int(data["i"])) def qdumpHelper_QVariant_3(d, data): # uint - d.putBetterType("%sQVariant (uint)" % d.ns) + d.putBetterType("%sQVariant (uint)" % d.qtNamespace()) d.putValue(int(data["u"])) def qdumpHelper_QVariant_4(d, data): # qlonglong - d.putBetterType("%sQVariant (qlonglong)" % d.ns) + d.putBetterType("%sQVariant (qlonglong)" % d.qtNamespace()) d.putValue(int(data["ll"])) def qdumpHelper_QVariant_5(d, data): # qulonglong - d.putBetterType("%sQVariant (qulonglong)" % d.ns) + d.putBetterType("%sQVariant (qulonglong)" % d.qtNamespace()) d.putValue(int(data["ull"])) def qdumpHelper_QVariant_6(d, data): # QVariant::Double - d.putBetterType("%sQVariant (double)" % d.ns) + d.putBetterType("%sQVariant (double)" % d.qtNamespace()) d.putValue(float(data["d"])) qdumpHelper_QVariants_A = [ @@ -1893,7 +1901,7 @@ def qdumpHelper__QVariant(d, value): else: innert = qdumpHelper_QVariants_C[variantType - 64] - inner = d.ns + innert + inner = d.qtNamespace() + innert innerType = d.lookupType(inner) sizePD = 8 # sizeof(QVariant::Private::Data) @@ -1908,7 +1916,7 @@ def qdumpHelper__QVariant(d, value): d.putEmptyValue(-99) d.putItem(val) - d.putBetterType("%sQVariant (%s)" % (d.ns, innert)) + d.putBetterType("%sQVariant (%s)" % (d.qtNamespace(), innert)) return (None, innert, True) @@ -1922,14 +1930,15 @@ def qdump__QVariant(d, value): # User types. d_ptr = value["d"] typeCode = int(d_ptr["type"]) + ns = d.qtNamespace() 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)) except: - exp = "%sQMetaType::typeName(%d)" % (d.ns, typeCode) + exp = "%sQMetaType::typeName(%d)" % (ns, typeCode) type = str(d.parseAndEvaluate(exp)) 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("COMMA", ",") # HACK! type = type.replace(" ,", ",") # Lldb @@ -1937,7 +1946,7 @@ def qdump__QVariant(d, value): data = d.call(value, "constData") #warn("DATA: %s" % data) d.putEmptyValue(-99) - d.putType("%sQVariant (%s)" % (d.ns, type)) + d.putType("%sQVariant (%s)" % (ns, type)) d.putNumChild(1) tdata = data.cast(d.lookupType(type).pointer()).dereference() if d.isExpanded(): @@ -2075,7 +2084,7 @@ def qdump__QTJSC__JSValue(d, value): try: # 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) #d.putSubItem("delegate", delegate) variant = delegate["m_value"] @@ -2096,21 +2105,22 @@ def qdump__QScriptValue(d, value): # type QScriptValuePrivate::Type: { JavaScriptCore, Number, String } #d.putEmptyValue() dd = value["d_ptr"]["d"] + ns = d.qtNamespace() if d.isNull(dd): d.putValue("(invalid)") d.putNumChild(0) return if int(dd["type"]) == 1: # Number d.putValue(dd["numberValue"]) - d.putType("%sQScriptValue (Number)" % d.ns) + d.putType("%sQScriptValue (Number)" % ns) d.putNumChild(0) return if int(dd["type"]) == 2: # String d.putStringValue(dd["stringValue"]) - d.putType("%sQScriptValue (String)" % d.ns) + d.putType("%sQScriptValue (String)" % ns) return - d.putType("%sQScriptValue (JSCoreValue)" % d.ns) + d.putType("%sQScriptValue (JSCoreValue)" % ns) x = dd["jscValue"]["u"] tag = x["asBits"]["tag"] payload = x["asBits"]["payload"] @@ -2144,11 +2154,11 @@ def qdump__QScriptValue(d, value): try: # This might already fail for "native" payloads. - scriptObjectType = d.lookupType(d.ns + "QScriptObject").pointer() + scriptObjectType = d.lookupType(ns + "QScriptObject").pointer() scriptObject = payload.cast(scriptObjectType) # 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) #d.putSubItem("delegate", delegate) @@ -2156,7 +2166,7 @@ def qdump__QScriptValue(d, value): #d.putSubItem("variant", variant) t = qdump__QVariant(d, variant) # Override the "QVariant (foo)" output - d.putBetterType("%sQScriptValue (%s)" % (d.ns, t)) + d.putBetterType("%sQScriptValue (%s)" % (ns, t)) if t != "JSCoreValue": return except: diff --git a/share/qtcreator/debugger/stdtypes.py b/share/qtcreator/debugger/stdtypes.py index c29cbfed11a6b6837790c4427883b400b23a687c..a6270f91421b065cd3ed8c14b99686a19c93acfb 100644 --- a/share/qtcreator/debugger/stdtypes.py +++ b/share/qtcreator/debugger/stdtypes.py @@ -321,7 +321,7 @@ def qdump__std__stringHelper1(d, value, charSize): qdump_stringHelper(d, sizePtr, size * charSize, charSize) def qdump_stringHelper(d, data, size, charSize): - cutoff = min(size, qqStringCutOff) + cutoff = min(size, d.stringCutOff) mem = d.readMemory(data, cutoff) if charSize == 1: encodingType = Hex2EncodedLatin1 diff --git a/tests/auto/debugger/tst_dumpers.cpp b/tests/auto/debugger/tst_dumpers.cpp index bf4b3516be917e267407459181ab7c7d64b41dbf..fe35584485cb0973a09cf7afadac8d85864cba39 100644 --- a/tests/auto/debugger/tst_dumpers.cpp +++ b/tests/auto/debugger/tst_dumpers.cpp @@ -910,7 +910,7 @@ void tst_Dumpers::dumper() "python from gdbbridge import *\n" "run " + nograb + "\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"; } else { cmds += "run\n";