From 780c8283e95b90d97a44d4de8713b98cb014f851 Mon Sep 17 00:00:00 2001 From: hjk Date: Fri, 17 May 2013 17:14:45 +0200 Subject: [PATCH] Debugger: Adjust QList dumpers to LLDB needs Change-Id: I01071510d422176b632bcaf93e009ad5056ea777 Reviewed-by: hjk --- share/qtcreator/dumper/gbridge.py | 20 ++++----- share/qtcreator/dumper/lbridge.py | 55 +++++++++++++++-------- share/qtcreator/dumper/qttypes.py | 74 +++++++++++++------------------ 3 files changed, 77 insertions(+), 72 deletions(-) diff --git a/share/qtcreator/dumper/gbridge.py b/share/qtcreator/dumper/gbridge.py index debc73208a..238b84622b 100644 --- a/share/qtcreator/dumper/gbridge.py +++ b/share/qtcreator/dumper/gbridge.py @@ -25,14 +25,12 @@ gdbLoaded = True def warn(message): print "XXX: %s\n" % message.encode("latin1") -def valueAddressAsInt(value): - return long(value.address) +def directBaseClass(typeobj, index = 0): + # FIXME: Check it's really a base. + return typeobj.fields()[index] -def pointerAsInt(value): - return long(value) - -def asInt(value): - return int(value) +def createPointerValue(context, address, pointeeType): + return gdb.Value(address).cast(pointeeType.pointer()) def savePrint(output): try: @@ -471,9 +469,6 @@ def childAt(value, index): # them transparently. return value -def addressOf(value): - return gdb.Value(value.address).cast(value.type.pointer()) - #gdb.Value.child = impl_Value_child @@ -1589,6 +1584,9 @@ class Dumper: def voidPtrSize(self): return self.voidPtrType().sizeof + def addressOf(self, value): + return long(value.address) + def put(self, value): self.output.append(value) @@ -1624,7 +1622,7 @@ class Dumper: self.putNumChild(0) self.currentValue = None - def putBetterType(self, type, priority = 0): + def putBetterType(self, type): self.currentType = str(type) self.currentTypePriority = self.currentTypePriority + 1 diff --git a/share/qtcreator/dumper/lbridge.py b/share/qtcreator/dumper/lbridge.py index 2971f5fd17..77cc2d9b20 100644 --- a/share/qtcreator/dumper/lbridge.py +++ b/share/qtcreator/dumper/lbridge.py @@ -95,14 +95,11 @@ qqEditable = {} # This keeps canonical forms of the typenames, without array indices etc. qqStripForFormat = {} -def valueAddressAsInt(value): - return value.AddressOf().GetValueAsUnsigned() +def templateArgument(typeobj, index): + return typeobj.GetTemplateArgumentType(index) -def pointerAsInt(value): - return value.GetValueAsUnsigned() - -def templateArgument(type, index): - return type.GetTemplateArgumentType(index) +def directBaseClass(typeobj, index = 0): + return typeobj.GetDirectBaseClassAtIndex(index) def stripForFormat(typeName): global qqStripForFormat @@ -268,22 +265,32 @@ def checkRef(ref): check(count >= minimum) check(count < 1000000) +def createPointerValue(context, address, pointeeType): + addr = int(address) & 0xFFFFFFFFFFFFFFFF + return context.CreateValueFromAddress(None, addr, pointeeType).AddressOf() + def impl_SBValue__add__(self, offset): if self.GetType().IsPointerType(): - address = self.GetValueAsUnsigned() + offset.GetValueAsSigned() + if isinstance(offset, int) or isinstance(offset, long): + pass + else: + offset = offset.GetValueAsSigned() + itemsize = self.GetType().GetDereferencedType().GetByteSize() + address = self.GetValueAsUnsigned() + offset * itemsize address = address & 0xFFFFFFFFFFFFFFFF # Force unsigned - return self.CreateValueFromAddress(None, address, self.GetType()) + return createPointerValue(self, address, self.GetType().GetPointeeType()) raise RuntimeError("SBValue.__add__ not implemented: %s" % self.GetType()) return NotImplemented def impl_SBValue__sub__(self, other): if self.GetType().IsPointerType(): - if isinstance(other, int): - return self.GetChildAtIndex(-other, lldb.eNoDynamicValues, True).AddressOf() + if isinstance(other, int) or isinstance(other, long): + address = self.GetValueAsUnsigned() - offset.GetValueAsSigned() + address = address & 0xFFFFFFFFFFFFFFFF # Force unsigned + return self.CreateValueFromAddress(None, address, self.GetType()) if other.GetType().IsPointerType(): itemsize = self.GetType().GetDereferencedType().GetByteSize() return (int(self) - int(other)) / itemsize - return impl_SBValue__add__(self, -int(other)) raise RuntimeError("SBValue.__sub__ not implemented: %s" % self.GetType()) return NotImplemented @@ -294,7 +301,8 @@ def impl_SBValue__le__(self, other): return NotImplemented def impl_SBValue__int__(self): - return int(self.GetValue(), 0) + return self.GetValueAsSigned() + #return int(self.GetValue(), 0) def impl_SBValue__long__(self): return int(self.GetValue(), 0) @@ -310,9 +318,6 @@ def impl_SBValue__getitem__(self, name): def childAt(value, index): return value.GetChildAtIndex(index) -def addressOf(value): - return value.address_of - lldb.SBValue.__add__ = impl_SBValue__add__ lldb.SBValue.__sub__ = impl_SBValue__sub__ lldb.SBValue.__le__ = impl_SBValue__le__ @@ -547,6 +552,9 @@ class Dumper: self.sizetType_ = self.lookupType('size_t') return self.sizetType_ + def addressOf(self, value): + return int(value.GetLoadAddress()) + def handleCommand(self, command): result = lldb.SBCommandReturnObject() self.debugger.GetCommandInterpreter().HandleCommand(command, result) @@ -757,14 +765,23 @@ class Dumper: self.currentType = str(type) self.currentTypePriority = priority - def putBetterType(self, type, priority = 0): - self.currentType = str(type) + def putBetterType(self, type): + try: + self.currentType = type.GetName() + except: + self.currentType = str(type) self.currentTypePriority = self.currentTypePriority + 1 def readRawMemory(self, base, size): error = lldb.SBError() - contents = self.process.ReadMemory(base.GetLoadAddress(), size, error) + #warn("BASE: %s " % base) + #warn("SIZE: %s " % size) + base = int(base) & 0xFFFFFFFFFFFFFFFF + size = int(size) & 0xFFFFFFFF + #warn("BASEX: %s " % base) + #warn("SIZEX: %s " % size) + contents = self.process.ReadMemory(base, size, error) return binascii.hexlify(contents) def computeLimit(self, size, limit): diff --git a/share/qtcreator/dumper/qttypes.py b/share/qtcreator/dumper/qttypes.py index aea7a4a505..9d77127153 100644 --- a/share/qtcreator/dumper/qttypes.py +++ b/share/qtcreator/dumper/qttypes.py @@ -67,14 +67,15 @@ def qdump__QBasicAtomicPointer(d, value): d.putItem(value["_q_value"]) def qByteArrayData(d, value): - private = value['d'] + private = value['d'].dereference() checkRef(private['ref']) size = int(private['size']) alloc = int(private['alloc']) try: # Qt 5. Will fail on Qt 4 due to the missing 'offset' member. - offset = private['offset'] - data = private.cast(d.charPtrType()) + offset + offset = int(private['offset']) + addr = d.addressOf(private) + offset + data = createPointerValue(value, addr, d.charType()) return data, size, alloc except: # Qt 4: @@ -597,22 +598,17 @@ def qdump__QHostAddress(d, value): d.putFields(data) def qdump__QList(d, value): - d_ptr = childAt(value, 0)["d"].dereference() - begin = int(d_ptr["begin"]) - end = int(d_ptr["end"]) - array = addressOf(d_ptr["array"]) + dptr = childAt(value, 0)["d"] + private = dptr.dereference() + begin = int(private["begin"]) + end = int(private["end"]) + array = private["array"] check(begin >= 0 and end >= 0 and end <= 1000 * 1000 * 1000) size = end - begin check(size >= 0) - checkRef(d_ptr["ref"]) + checkRef(private["ref"]) - # Additional checks on pointer arrays. innerType = templateArgument(value.type, 0) - innerTypeIsPointer = innerType.code == PointerCode \ - and str(innerType.target().unqualified()) != "char" - if innerTypeIsPointer: - p = array.cast(innerType.pointer()) + begin - checkPointerRange(p, min(size, 100)) d.putItemCount(size) d.putNumChild(size) @@ -623,21 +619,25 @@ def qdump__QList(d, value): # but this data is available neither in the compiled binary nor # in the frontend. # So as first approximation only do the 'isLarge' check: - isInternal = innerSize <= d_ptr.type.sizeof and d.isMovableType(innerType) - innerTypePointer = innerType.pointer() - p = array.cast(d.charPtrType().pointer()) + begin - if innerTypeIsPointer: - inner = innerType.target() + stepSize = dptr.type.sizeof + isInternal = innerSize <= stepSize and d.isMovableType(innerType) + addr = d.addressOf(array) + begin * stepSize + if isInternal: + if innerSize == stepSize: + p = createPointerValue(value, addr, innerType) + d.putArrayData(innerType, p, size) + else: + with Children(d, size, childType=innerType): + for i in d.childRange(): + p = createPointerValue(value, addr + i * stepSize, innerType) + d.putSubItem(i, p.dereference()) else: - inner = innerType - # about 0.5s / 1000 items - with Children(d, size, maxNumChild=2000, childType=inner): - for i in d.childRange(): - if isInternal: - d.putSubItem(i, p.cast(innerTypePointer).dereference()) - else: - d.putSubItem(i, p.cast(innerTypePointer.pointer()).dereference()) - p += 1 + p = createPointerValue(value, addr, innerType.pointer()) + # about 0.5s / 1000 items + with Children(d, size, maxNumChild=2000, childType=innerType): + for i in d.childRange(): + d.putSubItem(i, p.dereference().dereference()) + p += 1 def qform__QImage(): return "Normal,Displayed" @@ -1585,19 +1585,9 @@ def qdump__QStringRef(d, value): def qdump__QStringList(d, value): - d_ptr = value['d'] - begin = d_ptr['begin'] - end = d_ptr['end'] - size = end - begin - check(size >= 0) - check(size <= 10 * 1000 * 1000) - checkRef(d_ptr["ref"]) - d.putItemCount(size) - d.putNumChild(size) - if d.isExpanded(): - innerType = d.lookupType(d.ns + "QString") - innerTypePP = innerType.pointer().pointer() - d.putArrayData(innerType, d_ptr["array"].cast(innerTypePP) + begin, size, 0) + listType = directBaseClass(value.type).type + qdump__QList(d, value.cast(listType)) + d.putBetterType(value.type) def qdump__QTemporaryFile(d, value): @@ -2199,7 +2189,7 @@ def qdump__std__string(d, value): sizePtr = data.cast(d.sizetType().pointer()) size = int(sizePtr[-3]) alloc = int(sizePtr[-2]) - refcount = int(sizePtr[-1]) & 0xffffffff + refcount = int(sizePtr[-1]) check(refcount >= -1) # Can be -1 accoring to docs. check(0 <= size and size <= alloc and alloc <= 100*1000*1000) -- GitLab