Commit 2e7479ae authored by hjk's avatar hjk

Debugger: Add data extraction for dumper inferior call results.

Change-Id: I868be727c48cb3aa570f196dadde71706df01596
Reviewed-by: default avatarhjk <hjk121@nokiamail.com>
parent cb53eacc
......@@ -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
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]
if hasattr(encoded, "decode"):
return encoded.decode("utf8")
return encoded
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.
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment