Commit a036f7f1 authored by hjk's avatar hjk
Browse files

Debugger: Fix more LLDB dumpers



Simple QVariants, references, const pointers, QObject names,
QList<Foo*>, ...

Change-Id: Iaa3fb9e4db1c249817e59239029db7dd220ba5b3
Reviewed-by: default avatarhjk <hjk121@nokiamail.com>
parent b05603a4
......@@ -1777,6 +1777,12 @@ class Dumper:
self.put('",')
return True
def isReferenceType(self, typeobj):
return typeobj.code == gdb.TYPE_CODE_REF
def isStructType(self, typeobj):
return typeobj.code == gdb.TYPE_CODE_STRUCT
def putPlotData(self, type, base, n, plotFormat):
if self.isExpanded():
self.putArrayData(type, base, n)
......
......@@ -73,9 +73,6 @@ DisplayLatin1String, \
DisplayUtf8String \
= range(7)
def lookupType(name):
return None
def isSimpleType(typeobj):
typeClass = typeobj.GetTypeClass()
#warn("TYPECLASS: %s" % typeClass)
......@@ -179,36 +176,7 @@ def fileName(file):
return str(file) if file.IsValid() else ''
PointerCode = None
ArrayCode = None
StructCode = None
UnionCode = None
EnumCode = None
FlagsCode = None
FunctionCode = None
IntCode = None
FloatCode = None
VoidCode = None
SetCode = None
RangeCode = None
StringCode = None
BitStringCode = None
ErrorTypeCode = None
MethodCode = None
MethodPointerCode = None
MemberPointerCode = None
ReferenceCode = None
CharCode = None
BoolCode = None
ComplexCode = None
TypedefCode = None
NamespaceCode = None
SimpleValueCode = None # LLDB only
# Data members
SimpleValueCode = 100
StructCode = 101
PointerCode = 102
# Breakpoints. Keep synchronized with BreakpointType in breakpoint.h
......@@ -245,7 +213,7 @@ def checkPointer(p, align = 1):
p.Dereference()
def isNull(p):
return long(p) == 0
return p.GetValueAsUnsigned() == 0
Value = lldb.SBValue
......@@ -340,9 +308,6 @@ lldb.SBType.__str__ = lldb.SBType.GetName
def simpleEncoding(typeobj):
code = typeobj.GetTypeClass()
size = typeobj.sizeof
#if code == BoolCode or code == CharCode:
# return Hex2EncodedInt1
#if code == IntCode:
if code == lldb.eTypeClassBuiltin:
name = str(typeobj)
if name == "float":
......@@ -390,7 +355,7 @@ class Children:
#if isSimpleType(childType):
# self.d.put('childnumchild="0",')
# self.childNumChild = 0
#elif childType.code == PointerCode:
#elif childType.code == lldb.eTypeClassPointer:
# self.d.put('childnumchild="1",')
# self.childNumChild = 1
else:
......@@ -469,6 +434,8 @@ class SubItem:
self.d.put('{')
#if not self.name is None:
if isinstance(self.name, str):
if self.name == '**&':
self.name = '*'
self.d.put('name="%s",' % self.name)
self.savedIName = self.d.currentIName
self.savedCurrentAddress = self.d.currentAddress
......@@ -597,7 +564,7 @@ class Dumper:
def templateArgument(self, typeobj, index):
type = typeobj.GetTemplateArgumentType(index)
if len(type.GetName()):
if type.IsValid():
return type
inner = self.extractTemplateArgument(typeobj.GetName(), index)
return self.lookupType(inner)
......@@ -606,6 +573,12 @@ class Dumper:
inner = self.extractTemplateArgument(typeobj.GetName(), index)
return int(inner)
def isReferenceType(self, typeobj):
return typeobj.IsReferenceType()
def isStructType(self, typeobj):
return typeobj.GetTypeClass() in (lldb.eTypeClassStruct, lldb.eTypeClassClass)
def qtVersion(self):
return 0x050000
......@@ -678,10 +651,11 @@ class Dumper:
return format
def isMovableType(self, type):
if type.code == PointerCode:
return True
if isSimpleType(type):
if type.GetTypeClass() in (lldb.eTypeClassBuiltin,
lldb.eTypeClassPointer):
return True
warn("MOVABLE: %s" % type)
warn("CODE: %s" % type.GetTypeClass())
return self.stripNamespaceFromType(type.GetName()) in movableTypes
def putIntItem(self, name, value):
......@@ -745,7 +719,7 @@ class Dumper:
return True
def putPlotData(self, type, base, n, plotFormat):
warn("PLOTDATA: %s %s" % (type, n))
#warn("PLOTDATA: %s %s" % (type, n))
if self.isExpanded():
self.putArrayData(type, base, n)
self.putValue(self.currentValue)
......@@ -789,9 +763,14 @@ class Dumper:
self.putFields(value)
def lookupType(self, name):
if name.endswith('*'):
type = self.lookupType(name[:-1].strip())
return type.GetPointerType() if type.IsValid() else None
#warn("LOOKUP TYPE NAME: %s" % name)
#warn("LOOKUP RESULT: %s" % self.target.FindFirstType(name))
return self.target.FindFirstType(name)
#warn("LOOKUP RESULT: %s" % self.target.FindFirstType(name))
type = self.target.FindFirstType(name)
return type if type.IsValid() else None
def setupInferior(self, args):
executable = args['executable']
......@@ -942,6 +921,17 @@ class Dumper:
contents = self.process.ReadMemory(base, size, error)
return binascii.hexlify(contents)
def isQObject(self, value):
try:
vtable = value.Cast(self.voidPtrType().GetPointerType())
metaObjectEntry = vtable.Dereference()
addr = lldb.SBAddress(long(metaObjectEntry), self.target)
symbol = addr.GetSymbol()
name = symbol.GetMangledName()
return name.find("10metaObjectEv") > 0
except:
return False
def computeLimit(self, size, limit):
if limit is None:
return size
......@@ -967,6 +957,10 @@ class Dumper:
pos1 = type.rfind(">", pos)
type = type[0:pos] + type[pos1+1:]
pos = type.find("<")
if type.startswith("const "):
type = type[6:]
if type.startswith("volatile "):
type = type[9:]
return type
def putSubItem(self, component, value, tryDynamic=True):
......@@ -987,6 +981,7 @@ class Dumper:
#value = value.GetDynamicValue(lldb.eDynamicCanRunTarget)
typeName = value.GetTypeName()
value.SetPreferDynamicValue(tryDynamic)
typeClass = value.GetType().GetTypeClass()
if tryDynamic:
self.putAddress(value.address)
......@@ -1020,38 +1015,53 @@ class Dumper:
value.SetPreferSyntheticValue(False)
# Arrays
if value.GetType().GetTypeClass() == lldb.eTypeClassArray:
if typeClass == lldb.eTypeClassArray:
qdump____c_style_array__(self, value)
return
# References
if value.GetType().IsReferenceType():
origType = value.GetTypeName();
type = value.GetType().GetDereferencedType()
addr = int(value.GetAddress()) & 0xFFFFFFFFFFFFFFFF
type = value.GetType().GetDereferencedType().GetUnqualifiedType()
addr = int(value) & 0xFFFFFFFFFFFFFFFF
self.putItem(value.CreateValueFromAddress(None, addr, type))
#self.putItem(value.CreateValueFromData(None, value.GetData(), type))
self.putBetterType(origType)
return
# Pointers
if value.GetType().IsPointerType() and self.autoDerefPointers:
if value.GetType().IsPointerType():
if isNull(value):
self.putType(typeName)
self.putValue("0x0")
self.putNumChild(0)
return
innerType = value.GetType().GetPointeeType()
self.putType(innerType)
savedCurrentChildType = self.currentChildType
self.currentChildType = str(innerType)
inner = value.Dereference()
if inner.IsValid():
self.putItem(inner)
self.currentChildType = savedCurrentChildType
self.put('origaddr="%s",' % value.address)
return
if self.autoDerefPointers:
innerType = value.GetType().GetPointeeType().GetUnqualifiedType()
self.putType(innerType)
savedCurrentChildType = self.currentChildType
self.currentChildType = str(innerType)
inner = value.Dereference()
if inner.IsValid():
self.putItem(inner)
self.currentChildType = savedCurrentChildType
self.put('origaddr="%s",' % value.address)
return
else:
numchild = value.GetNumChildren()
self.put('iname="%s",' % self.currentIName)
self.putType(typeName)
self.putValue('0x%x' % value.GetValueAsUnsigned())
self.put('numchild="1",')
self.put('addr="0x%x",' % value.GetLoadAddress())
if self.currentIName in self.expandedINames:
with Children(self):
child = value.Dereference()
with SubItem(self, child):
self.putItem(child)
#warn("VALUE: %s" % value)
#warn("FANCY: %s" % self.useFancy)
......@@ -1066,12 +1076,24 @@ class Dumper:
return
# Normal value
v = value.GetValue()
#numchild = 1 if value.MightHaveChildren() else 0
numchild = value.GetNumChildren()
self.put('iname="%s",' % self.currentIName)
self.putType(typeName)
self.putValue('' if v is None else v)
if typeClass == lldb.eTypeClassStruct or typeClass == lldb.eTypeClassClass:
if self.isQObject(value):
self.context = value
if not self.putQObjectNameValue(value): # Is this too expensive?
self.putEmptyValue()
else:
self.putEmptyValue()
else:
v = value.GetValue()
if v:
self.putValue(v)
else:
self.putEmptyValue()
self.put('numchild="%s",' % numchild)
self.put('addr="0x%x",' % value.GetLoadAddress())
if self.currentIName in self.expandedINames:
......
......@@ -161,7 +161,7 @@ def qPutQObjectNameValue(d, value):
# - QDynamicMetaObjectData *metaObject;
extra = d.dereference(dd + 5 * ptrSize + 2 * intSize)
if extra == 0:
return
return False
# Offset of objectName in ExtraData: 6 pointer
# - QVector<QObjectUserData *> userData; only #ifndef QT_NO_USERDATA
......@@ -174,9 +174,12 @@ def qPutQObjectNameValue(d, value):
data, size, alloc = qByteArrayData(d, objectName)
if size > 0:
str = d.readRawMemory(data, 2 * size)
d.putValue(str, Hex4EncodedLittleEndian, 1)
if size == 0:
return False
str = d.readRawMemory(data, 2 * size)
d.putValue(str, Hex4EncodedLittleEndian, 1)
return True
except:
pass
......@@ -1973,7 +1976,7 @@ def qdumpHelper__QVariant(d, value):
sizePD = d.lookupType(d.ns + 'QVariant::Private::Data').sizeof
if innerType.sizeof > sizePD:
sizePS = d.lookupType(d.ns + 'QVariant::PrivateShared').sizeof
val = (sizePS + data.cast(d.charPtrType())) \
val = (data.cast(d.charPtrType()) + sizePS) \
.cast(innerType.pointer()).dereference()
else:
val = data.cast(innerType)
......@@ -2573,7 +2576,7 @@ def qdump__boost__optional(d, value):
else:
type = d.templateArgument(value.type, 0)
storage = value["m_storage"]
if type.code == ReferenceCode:
if d.isReferenceType(type):
d.putItem(storage.cast(type.target().pointer()).dereference())
else:
d.putItem(storage.cast(type))
......@@ -2925,7 +2928,7 @@ def qdump__Eigen__Matrix(d, value):
nrows = value["m_storage"]["m_rows"] if argRow == -1 else int(argRow)
ncols = value["m_storage"]["m_cols"] if argCol == -1 else int(argCol)
p = storage["m_data"]
if p.type.code == StructCode: # Static
if d.isStructType(p.type): # Static
p = p["array"].cast(innerType.pointer())
d.putValue("(%s x %s), %s" % (nrows, ncols, ["ColumnMajor", "RowMajor"][rowMajor]))
d.putField("keeporder", "1")
......
......@@ -3138,16 +3138,28 @@ void tst_Dumpers::dumper_data()
% Check("this.@1", "[@QThread]", "\"This is thread #3\"", "@QThread")
% Check("this.@1.@1", "[@QObject]", "\"This is thread #3\"", "@QObject");
QTest::newRow("QVariant1")
QTest::newRow("QVariant0")
<< Data("#include <QVariant>\n",
"QVariant value;\n"
"QVariant::Type t = QVariant::String;\n"
"value = QVariant(t, (void*)0);\n"
"*(QString*)value.data() = QString(\"Some string\");\n")
% CoreProfile()
% GdbOnly()
% Check("t", "@QVariant::String (10)", "@QVariant::Type")
% Check("value", "\"Some string\"", "@QVariant (QString)");
QTest::newRow("QVariant1")
<< Data("#include <QVariant>\n",
"QVariant value;\n"
"QVariant::Type t = QVariant::String;\n"
"value = QVariant(t, (void*)0);\n"
"*(QString*)value.data() = QString(\"Some string\");\n")
% CoreProfile()
% LldbOnly()
% Check("t", "String", "@QVariant::Type")
% Check("value", "\"Some string\"", "@QVariant (QString)");
QTest::newRow("QVariant2")
<< Data("#include <QVariant>\n"
"#include <QRect>\n"
......
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