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 @@ ...@@ -28,6 +28,7 @@
############################################################################ ############################################################################
import os import os
import struct
import sys import sys
import base64 import base64
...@@ -70,16 +71,51 @@ class Blob(object): ...@@ -70,16 +71,51 @@ class Blob(object):
def size(self): def size(self):
return self.size return self.size
def toHexOutput(self): def toBytes(self):
if hasattr(self.data, "tobytes"): """Retrieves "lazy" contents from memoryviews."""
encoded = base64.b16encode(self.data.tobytes()) data = self.data
else: if isinstance(data, memoryview):
encoded = base64.b16encode(self.data) 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"): def extractLong(self, offset = 0):
return encoded.decode("utf8") return struct.unpack_from("l", self.data, offset)[0]
return encoded
# 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. # Gnuplot based display for array-like structures.
...@@ -296,17 +332,22 @@ class DumperBase: ...@@ -296,17 +332,22 @@ class DumperBase:
self.cachedFormats[typeName] = stripped self.cachedFormats[typeName] = stripped
return stripped return stripped
# Hex decoding operating on string->string # Hex decoding operating on str, return str.
def hexdecode(self, s): def hexdecode(self, s):
if sys.version_info[0] == 2: if sys.version_info[0] == 2:
return s.decode("hex") return s.decode("hex")
return bytes.fromhex(s).decode("utf8") 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): def hexencode(self, s):
if sys.version_info[0] == 2: if sys.version_info[0] == 2:
return s.encode("hex") 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): def isArmArchitecture(self):
return False return False
...@@ -379,7 +420,8 @@ class DumperBase: ...@@ -379,7 +420,8 @@ class DumperBase:
return s return s
def readMemory(self, addr, size): 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): def encodeByteArray(self, value):
return self.encodeByteArrayHelper(self.dereferenceValue(value)) return self.encodeByteArrayHelper(self.dereferenceValue(value))
......
...@@ -394,11 +394,11 @@ Value = gdb.Value ...@@ -394,11 +394,11 @@ Value = gdb.Value
def stripTypedefs(type): def stripTypedefs(typeobj):
type = type.unqualified() typeobj = typeobj.unqualified()
while type.code == TypedefCode: while typeobj.code == TypedefCode:
type = type.strip_typedefs().unqualified() typeobj = typeobj.strip_typedefs().unqualified()
return type return typeobj
####################################################################### #######################################################################
...@@ -497,8 +497,8 @@ class Dumper(DumperBase): ...@@ -497,8 +497,8 @@ class Dumper(DumperBase):
for f in arg[pos:].split(","): for f in arg[pos:].split(","):
pos = f.find("=") pos = f.find("=")
if pos != -1: if pos != -1:
type = self.hexdecode(f[0:pos]) typeName = self.hexdecode(f[0:pos])
self.typeformats[type] = int(f[pos+1:]) self.typeformats[typeName] = int(f[pos+1:])
elif arg.startswith("formats:"): elif arg.startswith("formats:"):
for f in arg[pos:].split(","): for f in arg[pos:].split(","):
pos = f.find("=") pos = f.find("=")
...@@ -565,11 +565,11 @@ class Dumper(DumperBase): ...@@ -565,11 +565,11 @@ class Dumper(DumperBase):
with OutputSafer(self): with OutputSafer(self):
self.anonNumber = -1 self.anonNumber = -1
type = value.type.unqualified() typeobj = value.type.unqualified()
typeName = str(type) typeName = str(typeobj)
# Special handling for char** argv. # Special handling for char** argv.
if type.code == PointerCode \ if typeobj.code == PointerCode \
and item.iname == "local.argv" \ and item.iname == "local.argv" \
and typeName == "char **": and typeName == "char **":
n = 0 n = 0
...@@ -616,13 +616,14 @@ class Dumper(DumperBase): ...@@ -616,13 +616,14 @@ class Dumper(DumperBase):
self.output.append('],typeinfo=[') self.output.append('],typeinfo=[')
for name in self.typesToReport.keys(): for name in self.typesToReport.keys():
type = self.typesToReport[name] typeobj = self.typesToReport[name]
# Happens e.g. for '(anonymous namespace)::InsertDefOperation' # 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.output.append('{name="%s",size="%s"}'
% (self.hexencode(name), type.sizeof)) % (self.hexencode(name), typeobj.sizeof))
self.output.append(']') self.output.append(']')
self.typesToReport = {} self.typesToReport = {}
return "".join(self.output) return "".join(self.output)
def enterSubItem(self, item): def enterSubItem(self, item):
...@@ -946,11 +947,9 @@ class Dumper(DumperBase): ...@@ -946,11 +947,9 @@ class Dumper(DumperBase):
return struct.unpack("q", self.readRawMemory(addr, 8))[0] return struct.unpack("q", self.readRawMemory(addr, 8))[0]
def extractInt(self, addr): def extractInt(self, addr):
#return long(gdb.Value(addr).cast(self.intPtrType()).dereference())
return struct.unpack("i", self.readRawMemory(addr, 4))[0] return struct.unpack("i", self.readRawMemory(addr, 4))[0]
def extractByte(self, addr): def extractByte(self, addr):
#return long(gdb.Value(addr).cast(self.charPtrType()).dereference()) & 0xFF
return struct.unpack("b", self.readRawMemory(addr, 1))[0] return struct.unpack("b", self.readRawMemory(addr, 1))[0]
# Do not use value.address here as this might not have one, # Do not use value.address here as this might not have one,
...@@ -1429,6 +1428,19 @@ class Dumper(DumperBase): ...@@ -1429,6 +1428,19 @@ class Dumper(DumperBase):
with Children(self): with Children(self):
self.putFields(value) 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): def extractBlob(self, base, size):
inferior = self.selectedInferior() inferior = self.selectedInferior()
return Blob(inferior.read_memory(base, size)) return Blob(inferior.read_memory(base, size))
......
...@@ -1964,43 +1964,40 @@ def qdump__QUrl(d, value): ...@@ -1964,43 +1964,40 @@ def qdump__QUrl(d, value):
d.putGenericItem("query", stringType, query, Hex4EncodedLittleEndian) d.putGenericItem("query", stringType, query, Hex4EncodedLittleEndian)
d.putGenericItem("fragment", stringType, fragment, Hex4EncodedLittleEndian) d.putGenericItem("fragment", stringType, fragment, Hex4EncodedLittleEndian)
def qdumpHelper_QVariant_0(d, data): def qdumpHelper_QVariant_0(d, blob):
# QVariant::Invalid # QVariant::Invalid
d.putBetterType("%sQVariant (invalid)" % d.qtNamespace()) d.putBetterType("%sQVariant (invalid)" % d.qtNamespace())
d.putValue("(invalid)") d.putValue("(invalid)")
def qdumpHelper_QVariant_1(d, data): def qdumpHelper_QVariant_1(d, blob):
# QVariant::Bool # QVariant::Bool
d.putBetterType("%sQVariant (bool)" % d.qtNamespace()) d.putBetterType("%sQVariant (bool)" % d.qtNamespace())
if int(data["b"]): d.putValue("true" if blob.extractByte() else "false")
d.putValue("true")
else:
d.putValue("false")
def qdumpHelper_QVariant_2(d, data): def qdumpHelper_QVariant_2(d, blob):
# QVariant::Int # QVariant::Int
d.putBetterType("%sQVariant (int)" % d.qtNamespace()) 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 # uint
d.putBetterType("%sQVariant (uint)" % d.qtNamespace()) 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 # qlonglong
d.putBetterType("%sQVariant (qlonglong)" % d.qtNamespace()) 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 # qulonglong
d.putBetterType("%sQVariant (qulonglong)" % d.qtNamespace()) 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 # QVariant::Double
d.putBetterType("%sQVariant (double)" % d.qtNamespace()) d.putBetterType("%sQVariant (double)" % d.qtNamespace())
d.putValue(float(data["d"])) d.putValue(blob.extractDouble())
qdumpHelper_QVariants_A = [ qdumpHelper_QVariants_A = [
qdumpHelper_QVariant_0, qdumpHelper_QVariant_0,
...@@ -2038,45 +2035,45 @@ qdumpHelper_QVariants_B = [ ...@@ -2038,45 +2035,45 @@ qdumpHelper_QVariants_B = [
"QVariantHash",# 28 "QVariantHash",# 28
] ]
def qdumpHelper_QVariant_31(d, data): def qdumpHelper_QVariant_31(d, blob):
# QVariant::VoidStart # QVariant::VoidStart
d.putBetterType("%sQVariant (void *)" % d.qtNamespace()) 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 # QVariant::Long
d.putBetterType("%sQVariant (long)" % d.qtNamespace()) 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 # QVariant::Short
d.putBetterType("%sQVariant (short)" % d.qtNamespace()) 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 # QVariant::Char
d.putBetterType("%sQVariant (char)" % d.qtNamespace()) 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 # QVariant::ULong
d.putBetterType("%sQVariant (unsigned long)" % d.qtNamespace()) 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 # QVariant::UShort
d.putBetterType("%sQVariant (unsigned short)" % d.qtNamespace()) 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 # QVariant::UChar
d.putBetterType("%sQVariant (unsigned char)" % d.qtNamespace()) 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 # QVariant::Float
d.putBetterType("%sQVariant (float)" % d.qtNamespace()) d.putBetterType("%sQVariant (float)" % d.qtNamespace())
d.putValue("%f" % data["f"]) d.putValue("%s" % blob.extractFloat())
qdumpHelper_QVariants_D = [ qdumpHelper_QVariants_D = [
qdumpHelper_QVariant_31, qdumpHelper_QVariant_31,
...@@ -2118,16 +2115,17 @@ qdumpHelper_QVariants_E = [ ...@@ -2118,16 +2115,17 @@ qdumpHelper_QVariants_E = [
def qdumpHelper__QVariant(d, value): def qdumpHelper__QVariant(d, value):
data = value["d"]["data"] data = value["d"]["data"]
variantType = int(value["d"]["type"]) variantType = int(value["d"]["type"])
blob = d.toBlob(data)
#warn("VARIANT TYPE: %s : " % variantType) #warn("VARIANT TYPE: %s : " % variantType)
# Well-known simple type. # Well-known simple type.
if variantType <= 6: if variantType <= 6:
qdumpHelper_QVariants_A[variantType](d, data) qdumpHelper_QVariants_A[variantType](d, blob)
d.putNumChild(0) d.putNumChild(0)
return (None, None, True) return (None, None, True)
if variantType >= 31 and variantType <= 38: if variantType >= 31 and variantType <= 38:
qdumpHelper_QVariants_D[variantType - 31](d, data) qdumpHelper_QVariants_D[variantType - 31](d, blob)
d.putNumChild(0) d.putNumChild(0)
return (None, None, True) return (None, None, True)
...@@ -2147,6 +2145,7 @@ def qdumpHelper__QVariant(d, value): ...@@ -2147,6 +2145,7 @@ def qdumpHelper__QVariant(d, value):
sizePD = 8 # sizeof(QVariant::Private::Data) sizePD = 8 # sizeof(QVariant::Private::Data)
isSpecial = d.qtVersion() >= 0x050000 \ isSpecial = d.qtVersion() >= 0x050000 \
and (innert == "QVariantMap" or innert == "QVariantHash") and (innert == "QVariantMap" or innert == "QVariantHash")
#warn("IS SPECIAL: %s" % special)
if innerType.sizeof > sizePD or isSpecial: if innerType.sizeof > sizePD or isSpecial:
val = data["ptr"].cast(innerType.pointer().pointer()).dereference().dereference() val = data["ptr"].cast(innerType.pointer().pointer()).dereference().dereference()
else: else:
......
...@@ -4527,12 +4527,7 @@ namespace qvariant { ...@@ -4527,12 +4527,7 @@ namespace qvariant {
BREAK_HERE; BREAK_HERE;
// Check vm <0 items> QVariantMap. // Check vm <0 items> QVariantMap.
// Continue. // Continue.
vm["a"] = QVariant(1); vm["abd"] = QVariant(1);
vm["b"] = QVariant(2);
vm["c"] = QVariant("Some String");
vm["d"] = QVariant(21);
vm["e"] = QVariant(22);
vm["f"] = QVariant("2Some String");
BREAK_HERE; BREAK_HERE;
// Expand vm vm.0 vm.5. // Expand vm vm.0 vm.5.
// Check vm <6 items> QVariantMap. // 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