forked from qt-creator/qt-creator
Debugger: Adjust QList dumpers to LLDB needs
Change-Id: I01071510d422176b632bcaf93e009ad5056ea777 Reviewed-by: hjk <hjk121@nokiamail.com>
This commit is contained in:
@@ -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
|
||||
|
||||
|
||||
@@ -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):
|
||||
|
||||
@@ -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)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user