forked from qt-creator/qt-creator
Debugger: Add data extraction for dumper inferior call results.
Change-Id: I868be727c48cb3aa570f196dadde71706df01596 Reviewed-by: hjk <hjk121@nokiamail.com>
This commit is contained in:
@@ -28,6 +28,7 @@
|
||||
############################################################################
|
||||
|
||||
import os
|
||||
import struct
|
||||
import sys
|
||||
import base64
|
||||
|
||||
@@ -70,16 +71,51 @@ class Blob(object):
|
||||
def size(self):
|
||||
return self.size
|
||||
|
||||
def toHexOutput(self):
|
||||
if hasattr(self.data, "tobytes"):
|
||||
encoded = base64.b16encode(self.data.tobytes())
|
||||
else:
|
||||
encoded = base64.b16encode(self.data)
|
||||
def toBytes(self):
|
||||
"""Retrieves "lazy" contents from memoryviews."""
|
||||
data = self.data
|
||||
if isinstance(data, memoryview):
|
||||
data = data.tobytes()
|
||||
if sys.version_info[0] == 2 and isinstance(data, buffer):
|
||||
data = ''.join([c for c in data])
|
||||
return data
|
||||
|
||||
if hasattr(encoded, "decode"):
|
||||
return encoded.decode("utf8")
|
||||
return encoded
|
||||
def extractByte(self, offset = 0):
|
||||
return struct.unpack_from("b", self.data, offset)[0]
|
||||
|
||||
def extractShort(self, offset = 0):
|
||||
return struct.unpack_from("h", self.data, offset)[0]
|
||||
|
||||
def extractUShort(self, offset = 0):
|
||||
return struct.unpack_from("H", self.data, offset)[0]
|
||||
|
||||
def extractInt(self, offset = 0):
|
||||
return struct.unpack_from("i", self.data, offset)[0]
|
||||
|
||||
def extractUInt(self, offset = 0):
|
||||
return struct.unpack_from("I", self.data, offset)[0]
|
||||
|
||||
def extractLong(self, offset = 0):
|
||||
return struct.unpack_from("l", self.data, offset)[0]
|
||||
|
||||
# FIXME: Note these should take target architecture into account.
|
||||
def extractULong(self, offset = 0):
|
||||
return struct.unpack_from("L", self.data, offset)[0]
|
||||
|
||||
def extractInt64(self, offset = 0):
|
||||
return struct.unpack_from("q", self.data, offset)[0]
|
||||
|
||||
def extractUInt64(self, offset = 0):
|
||||
return struct.unpack_from("Q", self.data, offset)[0]
|
||||
|
||||
def extractDouble(self, offset = 0):
|
||||
return struct.unpack_from("d", self.data, offset)[0]
|
||||
|
||||
def extractFloat(self, offset = 0):
|
||||
return struct.unpack_from("f", self.data, offset)[0]
|
||||
|
||||
def extractPointer(self, offset = 0):
|
||||
return struct.unpack_from("P", self.data, offset)[0]
|
||||
|
||||
#
|
||||
# Gnuplot based display for array-like structures.
|
||||
@@ -296,17 +332,22 @@ class DumperBase:
|
||||
self.cachedFormats[typeName] = stripped
|
||||
return stripped
|
||||
|
||||
# Hex decoding operating on string->string
|
||||
# Hex decoding operating on str, return str.
|
||||
def hexdecode(self, s):
|
||||
if sys.version_info[0] == 2:
|
||||
return s.decode("hex")
|
||||
return bytes.fromhex(s).decode("utf8")
|
||||
|
||||
# Hex decoding operating on string->string
|
||||
# Hex decoding operating on str or bytes, return str.
|
||||
def hexencode(self, s):
|
||||
if sys.version_info[0] == 2:
|
||||
return s.encode("hex")
|
||||
return base64.b16encode(s.encode("utf8")).decode("utf8")
|
||||
if isinstance(s, str):
|
||||
s = s.encode("utf8")
|
||||
return base64.b16encode(s).decode("utf8")
|
||||
|
||||
#def toBlob(self, value):
|
||||
# return self.extractBlob(value.address, value.type.sizeof)
|
||||
|
||||
def isArmArchitecture(self):
|
||||
return False
|
||||
@@ -379,7 +420,8 @@ class DumperBase:
|
||||
return s
|
||||
|
||||
def readMemory(self, addr, size):
|
||||
return self.extractBlob(addr, size).toHexOutput()
|
||||
data = self.extractBlob(addr, size).toBytes()
|
||||
return self.hexencode(data)
|
||||
|
||||
def encodeByteArray(self, value):
|
||||
return self.encodeByteArrayHelper(self.dereferenceValue(value))
|
||||
|
@@ -394,11 +394,11 @@ Value = gdb.Value
|
||||
|
||||
|
||||
|
||||
def stripTypedefs(type):
|
||||
type = type.unqualified()
|
||||
while type.code == TypedefCode:
|
||||
type = type.strip_typedefs().unqualified()
|
||||
return type
|
||||
def stripTypedefs(typeobj):
|
||||
typeobj = typeobj.unqualified()
|
||||
while typeobj.code == TypedefCode:
|
||||
typeobj = typeobj.strip_typedefs().unqualified()
|
||||
return typeobj
|
||||
|
||||
|
||||
#######################################################################
|
||||
@@ -497,8 +497,8 @@ class Dumper(DumperBase):
|
||||
for f in arg[pos:].split(","):
|
||||
pos = f.find("=")
|
||||
if pos != -1:
|
||||
type = self.hexdecode(f[0:pos])
|
||||
self.typeformats[type] = int(f[pos+1:])
|
||||
typeName = self.hexdecode(f[0:pos])
|
||||
self.typeformats[typeName] = int(f[pos+1:])
|
||||
elif arg.startswith("formats:"):
|
||||
for f in arg[pos:].split(","):
|
||||
pos = f.find("=")
|
||||
@@ -565,11 +565,11 @@ class Dumper(DumperBase):
|
||||
with OutputSafer(self):
|
||||
self.anonNumber = -1
|
||||
|
||||
type = value.type.unqualified()
|
||||
typeName = str(type)
|
||||
typeobj = value.type.unqualified()
|
||||
typeName = str(typeobj)
|
||||
|
||||
# Special handling for char** argv.
|
||||
if type.code == PointerCode \
|
||||
if typeobj.code == PointerCode \
|
||||
and item.iname == "local.argv" \
|
||||
and typeName == "char **":
|
||||
n = 0
|
||||
@@ -616,13 +616,14 @@ class Dumper(DumperBase):
|
||||
|
||||
self.output.append('],typeinfo=[')
|
||||
for name in self.typesToReport.keys():
|
||||
type = self.typesToReport[name]
|
||||
typeobj = self.typesToReport[name]
|
||||
# Happens e.g. for '(anonymous namespace)::InsertDefOperation'
|
||||
if not type is None:
|
||||
if not typeobj is None:
|
||||
self.output.append('{name="%s",size="%s"}'
|
||||
% (self.hexencode(name), type.sizeof))
|
||||
% (self.hexencode(name), typeobj.sizeof))
|
||||
self.output.append(']')
|
||||
self.typesToReport = {}
|
||||
|
||||
return "".join(self.output)
|
||||
|
||||
def enterSubItem(self, item):
|
||||
@@ -946,11 +947,9 @@ class Dumper(DumperBase):
|
||||
return struct.unpack("q", self.readRawMemory(addr, 8))[0]
|
||||
|
||||
def extractInt(self, addr):
|
||||
#return long(gdb.Value(addr).cast(self.intPtrType()).dereference())
|
||||
return struct.unpack("i", self.readRawMemory(addr, 4))[0]
|
||||
|
||||
def extractByte(self, addr):
|
||||
#return long(gdb.Value(addr).cast(self.charPtrType()).dereference()) & 0xFF
|
||||
return struct.unpack("b", self.readRawMemory(addr, 1))[0]
|
||||
|
||||
# Do not use value.address here as this might not have one,
|
||||
@@ -1429,6 +1428,19 @@ class Dumper(DumperBase):
|
||||
with Children(self):
|
||||
self.putFields(value)
|
||||
|
||||
def toBlob(self, value):
|
||||
size = toInteger(value.type.sizeof)
|
||||
if value.address:
|
||||
return self.extractBlob(value.address, size)
|
||||
|
||||
# No address. Possibly the result of an inferior call.
|
||||
y = value.cast(gdb.lookup_type("unsigned char").array(0, int(size - 1)))
|
||||
buf = bytearray(struct.pack('x' * size))
|
||||
for i in range(size):
|
||||
buf[i] = int(y[i])
|
||||
|
||||
return Blob(bytes(buf))
|
||||
|
||||
def extractBlob(self, base, size):
|
||||
inferior = self.selectedInferior()
|
||||
return Blob(inferior.read_memory(base, size))
|
||||
|
@@ -1964,43 +1964,40 @@ def qdump__QUrl(d, value):
|
||||
d.putGenericItem("query", stringType, query, Hex4EncodedLittleEndian)
|
||||
d.putGenericItem("fragment", stringType, fragment, Hex4EncodedLittleEndian)
|
||||
|
||||
def qdumpHelper_QVariant_0(d, data):
|
||||
def qdumpHelper_QVariant_0(d, blob):
|
||||
# QVariant::Invalid
|
||||
d.putBetterType("%sQVariant (invalid)" % d.qtNamespace())
|
||||
d.putValue("(invalid)")
|
||||
|
||||
def qdumpHelper_QVariant_1(d, data):
|
||||
def qdumpHelper_QVariant_1(d, blob):
|
||||
# QVariant::Bool
|
||||
d.putBetterType("%sQVariant (bool)" % d.qtNamespace())
|
||||
if int(data["b"]):
|
||||
d.putValue("true")
|
||||
else:
|
||||
d.putValue("false")
|
||||
d.putValue("true" if blob.extractByte() else "false")
|
||||
|
||||
def qdumpHelper_QVariant_2(d, data):
|
||||
def qdumpHelper_QVariant_2(d, blob):
|
||||
# QVariant::Int
|
||||
d.putBetterType("%sQVariant (int)" % d.qtNamespace())
|
||||
d.putValue(int(data["i"]))
|
||||
d.putValue("%s" % blob.extractInt())
|
||||
|
||||
def qdumpHelper_QVariant_3(d, data):
|
||||
def qdumpHelper_QVariant_3(d, blob):
|
||||
# uint
|
||||
d.putBetterType("%sQVariant (uint)" % d.qtNamespace())
|
||||
d.putValue(int(data["u"]))
|
||||
d.putValue(blob.extractUInt())
|
||||
|
||||
def qdumpHelper_QVariant_4(d, data):
|
||||
def qdumpHelper_QVariant_4(d, blob):
|
||||
# qlonglong
|
||||
d.putBetterType("%sQVariant (qlonglong)" % d.qtNamespace())
|
||||
d.putValue(int(data["ll"]))
|
||||
d.putValue(blob.extractInt64())
|
||||
|
||||
def qdumpHelper_QVariant_5(d, data):
|
||||
def qdumpHelper_QVariant_5(d, blob):
|
||||
# qulonglong
|
||||
d.putBetterType("%sQVariant (qulonglong)" % d.qtNamespace())
|
||||
d.putValue(int(data["ull"]))
|
||||
d.putValue(blob.extractUInt64())
|
||||
|
||||
def qdumpHelper_QVariant_6(d, data):
|
||||
def qdumpHelper_QVariant_6(d, blob):
|
||||
# QVariant::Double
|
||||
d.putBetterType("%sQVariant (double)" % d.qtNamespace())
|
||||
d.putValue(float(data["d"]))
|
||||
d.putValue(blob.extractDouble())
|
||||
|
||||
qdumpHelper_QVariants_A = [
|
||||
qdumpHelper_QVariant_0,
|
||||
@@ -2038,45 +2035,45 @@ qdumpHelper_QVariants_B = [
|
||||
"QVariantHash",# 28
|
||||
]
|
||||
|
||||
def qdumpHelper_QVariant_31(d, data):
|
||||
def qdumpHelper_QVariant_31(d, blob):
|
||||
# QVariant::VoidStart
|
||||
d.putBetterType("%sQVariant (void *)" % d.qtNamespace())
|
||||
d.putValue("0x%x" % data["ptr"])
|
||||
d.putValue("0x%x" % blob.extractPointer())
|
||||
|
||||
def qdumpHelper_QVariant_32(d, data):
|
||||
def qdumpHelper_QVariant_32(d, blob):
|
||||
# QVariant::Long
|
||||
d.putBetterType("%sQVariant (long)" % d.qtNamespace())
|
||||
d.putValue(toInteger(data["l"]))
|
||||
d.putValue("%s" % blob.extractLong())
|
||||
|
||||
def qdumpHelper_QVariant_33(d, data):
|
||||
def qdumpHelper_QVariant_33(d, blob):
|
||||
# QVariant::Short
|
||||
d.putBetterType("%sQVariant (short)" % d.qtNamespace())
|
||||
d.putValue(toInteger(data["s"]))
|
||||
d.putValue("%s" % blob.extractShort())
|
||||
|
||||
def qdumpHelper_QVariant_34(d, data):
|
||||
def qdumpHelper_QVariant_34(d, blob):
|
||||
# QVariant::Char
|
||||
d.putBetterType("%sQVariant (char)" % d.qtNamespace())
|
||||
d.putValue(toInteger(data["c"]))
|
||||
d.putValue("%s" % blob.extractByte())
|
||||
|
||||
def qdumpHelper_QVariant_35(d, data):
|
||||
def qdumpHelper_QVariant_35(d, blob):
|
||||
# QVariant::ULong
|
||||
d.putBetterType("%sQVariant (unsigned long)" % d.qtNamespace())
|
||||
d.putValue(toInteger(data["ul"]))
|
||||
d.putValue("%s" % blob.extractULong())
|
||||
|
||||
def qdumpHelper_QVariant_36(d, data):
|
||||
def qdumpHelper_QVariant_36(d, blob):
|
||||
# QVariant::UShort
|
||||
d.putBetterType("%sQVariant (unsigned short)" % d.qtNamespace())
|
||||
d.putValue(toInteger(data["us"]))
|
||||
d.putValue("%s" % blob.extractUShort())
|
||||
|
||||
def qdumpHelper_QVariant_37(d, data):
|
||||
def qdumpHelper_QVariant_37(d, blob):
|
||||
# QVariant::UChar
|
||||
d.putBetterType("%sQVariant (unsigned char)" % d.qtNamespace())
|
||||
d.putValue(toInteger(data["uc"]))
|
||||
d.putValue("%s" % blob.extractByte())
|
||||
|
||||
def qdumpHelper_QVariant_38(d, data):
|
||||
def qdumpHelper_QVariant_38(d, blob):
|
||||
# QVariant::Float
|
||||
d.putBetterType("%sQVariant (float)" % d.qtNamespace())
|
||||
d.putValue("%f" % data["f"])
|
||||
d.putValue("%s" % blob.extractFloat())
|
||||
|
||||
qdumpHelper_QVariants_D = [
|
||||
qdumpHelper_QVariant_31,
|
||||
@@ -2118,16 +2115,17 @@ qdumpHelper_QVariants_E = [
|
||||
def qdumpHelper__QVariant(d, value):
|
||||
data = value["d"]["data"]
|
||||
variantType = int(value["d"]["type"])
|
||||
blob = d.toBlob(data)
|
||||
#warn("VARIANT TYPE: %s : " % variantType)
|
||||
|
||||
# Well-known simple type.
|
||||
if variantType <= 6:
|
||||
qdumpHelper_QVariants_A[variantType](d, data)
|
||||
qdumpHelper_QVariants_A[variantType](d, blob)
|
||||
d.putNumChild(0)
|
||||
return (None, None, True)
|
||||
|
||||
if variantType >= 31 and variantType <= 38:
|
||||
qdumpHelper_QVariants_D[variantType - 31](d, data)
|
||||
qdumpHelper_QVariants_D[variantType - 31](d, blob)
|
||||
d.putNumChild(0)
|
||||
return (None, None, True)
|
||||
|
||||
@@ -2147,6 +2145,7 @@ def qdumpHelper__QVariant(d, value):
|
||||
sizePD = 8 # sizeof(QVariant::Private::Data)
|
||||
isSpecial = d.qtVersion() >= 0x050000 \
|
||||
and (innert == "QVariantMap" or innert == "QVariantHash")
|
||||
#warn("IS SPECIAL: %s" % special)
|
||||
if innerType.sizeof > sizePD or isSpecial:
|
||||
val = data["ptr"].cast(innerType.pointer().pointer()).dereference().dereference()
|
||||
else:
|
||||
|
@@ -4527,12 +4527,7 @@ namespace qvariant {
|
||||
BREAK_HERE;
|
||||
// Check vm <0 items> QVariantMap.
|
||||
// Continue.
|
||||
vm["a"] = QVariant(1);
|
||||
vm["b"] = QVariant(2);
|
||||
vm["c"] = QVariant("Some String");
|
||||
vm["d"] = QVariant(21);
|
||||
vm["e"] = QVariant(22);
|
||||
vm["f"] = QVariant("2Some String");
|
||||
vm["abd"] = QVariant(1);
|
||||
BREAK_HERE;
|
||||
// Expand vm vm.0 vm.5.
|
||||
// Check vm <6 items> QVariantMap.
|
||||
|
Reference in New Issue
Block a user