diff options
author | hjk <hjk121@nokiamail.com> | 2014-01-24 17:02:23 +0100 |
---|---|---|
committer | hjk <hjk121@nokiamail.com> | 2014-01-24 17:36:27 +0100 |
commit | cc3facd9443dd9d3d192fd7984642437f17f9803 (patch) | |
tree | 2dc976483ea2e9da5c43054cae8b72b12450748a | |
parent | 864e61d63f17ad3027034f88b96522f1357dfcc9 (diff) | |
download | qt-creator-cc3facd9443dd9d3d192fd7984642437f17f9803.tar.gz |
Debugger: Enable QObject property display with LLDB
Finally.
Change-Id: I3257ffbb23ca2ea4eec9a97335a95580c9c4482b
Reviewed-by: hjk <hjk121@nokiamail.com>
-rw-r--r-- | share/qtcreator/debugger/dumper.py | 10 | ||||
-rw-r--r-- | share/qtcreator/debugger/gdbbridge.py | 3 | ||||
-rw-r--r-- | share/qtcreator/debugger/lldbbridge.py | 39 | ||||
-rw-r--r-- | tests/auto/debugger/tst_dumpers.cpp | 6 |
4 files changed, 26 insertions, 32 deletions
diff --git a/share/qtcreator/debugger/dumper.py b/share/qtcreator/debugger/dumper.py index 1502b5a5c2..63871ff87e 100644 --- a/share/qtcreator/debugger/dumper.py +++ b/share/qtcreator/debugger/dumper.py @@ -347,7 +347,7 @@ class DumperBase: return base64.b16encode(s).decode("utf8") #def toBlob(self, value): - # return self.extractBlob(value.address, value.type.sizeof) + # """Abstract""" def isArmArchitecture(self): return False @@ -897,7 +897,8 @@ class DumperBase: return True except: - self.knownNonQObjectTypes.insert(str(value.type)) + #warn("NO QOBJECT: %s" % value.type) + #self.knownNonQObjectTypes.add(str(value.type)) pass @@ -921,10 +922,7 @@ class DumperBase: # This is called is when a QObject derived class is expanded - def putQObjectGuts(self, qobject): - smo = self.childWithName(qobject, "staticMetaObject") - if smo is None: - return + def putQObjectGuts(self, qobject, smo): with SubItem(self, "[properties]"): propertyNames = self.staticQObjectPropertyNames(smo) propertyCount = len(propertyNames) diff --git a/share/qtcreator/debugger/gdbbridge.py b/share/qtcreator/debugger/gdbbridge.py index 8e878ec5c7..a77b804748 100644 --- a/share/qtcreator/debugger/gdbbridge.py +++ b/share/qtcreator/debugger/gdbbridge.py @@ -1418,7 +1418,8 @@ class Dumper(DumperBase): with Children(self, 1, childType=innerType): self.putFields(value) if isQObject: - self.putQObjectGuts(value) + smo = value["staticMetaObject"] + self.putQObjectGuts(value, smo) def putPlainChildren(self, value): diff --git a/share/qtcreator/debugger/lldbbridge.py b/share/qtcreator/debugger/lldbbridge.py index 2776cd2e49..6d80345522 100644 --- a/share/qtcreator/debugger/lldbbridge.py +++ b/share/qtcreator/debugger/lldbbridge.py @@ -79,6 +79,7 @@ import lldb qqWatchpointOffset = 10000 +lldb.theDumper = None def warn(message): print('\n\nWARNING="%s",\n' % message.encode("latin1").replace('"', "'")) @@ -182,16 +183,7 @@ def impl_SBValue__getitem__(value, index): address = address & 0xFFFFFFFFFFFFFFFF # Force unsigned return value.CreateValueFromAddress(None, address, innertype) return value.GetChildAtIndex(index) - result = value.GetChildMemberWithName(index) - if int(result.GetLoadAddress()) == 0xffffffffffffffff: - options = lldb.SBExpressionOptions() - typeClass = result.GetType().GetTypeClass() - if typeClass != lldb.eTypeClassBuiltin: - i = value.GetIndexOfChildWithName(index) - field = value.GetType().GetFieldAtIndex(i) - addr = value.GetLoadAddress() + field.GetOffsetInBytes() - result = value.CreateValueFromAddress(result.GetName(), addr, result.GetType()) - return result + return value.GetChildMemberWithName(index) def impl_SBValue__deref(value): result = value.Dereference() @@ -263,6 +255,8 @@ class Dumper(DumperBase): def __init__(self): DumperBase.__init__(self) + lldb.theDumper = self + self.debugger = lldb.SBDebugger.Create() #self.debugger.SetLoggingCallback(loggingCallback) #Same as: self.debugger.HandleCommand("log enable lldb dyld step") @@ -408,7 +402,7 @@ class Dumper(DumperBase): type = value.type.name exp = "((%s*)%s)->%s(%s)" % (type, value.address, func, arg) #warn("CALL: %s" % exp) - result = value.CreateValueFromExpression('$tmp', exp) + result = value.CreateValueFromExpression('', exp) #warn(" -> %s" % result) return result @@ -857,6 +851,9 @@ class Dumper(DumperBase): error = lldb.SBError() return Blob(self.process.ReadMemory(base, size, error)) + def readCArray(self, base, size): + return self.extractBlob(base, size).toBytes() + def toBlob(self, value): data = value.GetData() size = int(data.GetByteSize()) @@ -868,15 +865,9 @@ class Dumper(DumperBase): return Blob(bytes(buf)) 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 + needle = value.GetType().GetName() + "::staticMetaObject" + value = self.target.FindFirstGlobalVariable(needle) + return value.IsValid() def stripNamespaceFromType(self, typeName): #type = stripClassTag(typeName) @@ -898,7 +889,7 @@ class Dumper(DumperBase): def putSubItem(self, component, value, tryDynamic=True): if not value.IsValid(): - warn("INVALID SUBITEM") + warn("INVALID SUBITEM: %s" % value.GetName()) return with SubItem(self, component): self.putItem(value, tryDynamic) @@ -1004,8 +995,10 @@ class Dumper(DumperBase): #numchild = 1 if value.MightHaveChildren() else 0 numchild = value.GetNumChildren() self.putType(typeName) + isQObject = False if typeClass == lldb.eTypeClassStruct or typeClass == lldb.eTypeClassClass: if self.isQObject(value): + isQObject = True self.context = value if not self.putQObjectNameValue(value): # Is this too expensive? self.putEmptyValue() @@ -1023,6 +1016,10 @@ class Dumper(DumperBase): if self.currentIName in self.expandedINames: with Children(self): self.putFields(value) + if isQObject: + needle = value.GetType().GetName() + "::staticMetaObject" + smo = self.target.FindFirstGlobalVariable(needle) + self.putQObjectGuts(value, smo) def warn(self, msg): self.put('{name="%s",value="",type=""},' % msg) diff --git a/tests/auto/debugger/tst_dumpers.cpp b/tests/auto/debugger/tst_dumpers.cpp index 520c93a6a6..10f5cfbeec 100644 --- a/tests/auto/debugger/tst_dumpers.cpp +++ b/tests/auto/debugger/tst_dumpers.cpp @@ -2228,7 +2228,6 @@ void tst_Dumpers::dumper_data() QTest::newRow("QObject2") << Data("#include <QWidget>\n" "#include <QApplication>\n" - "namespace Names {\n" "namespace Bar {\n" " struct Ui { Ui() { w = 0; } QWidget *w; };\n" " class TestObject : public QObject\n" @@ -2257,11 +2256,10 @@ void tst_Dumpers::dumper_data() " QByteArray m_myProp2;\n" " };\n" "} // namespace Bar\n" - "} // namespace Names\n" "#include <main.moc>\n", "" "QApplication app(argc, argv);\n" - "Names::Bar::TestObject test;\n" + "Bar::TestObject test;\n" "test.setMyProp1(\"Hello\");\n" "test.setMyProp2(\"World\");\n" "QString s = test.myProp1();\n" @@ -2269,7 +2267,7 @@ void tst_Dumpers::dumper_data() "unused(&app, &test, &s);\n") % GuiProfile() % Check("s", "\"HelloWorld\"", "@QString") - % Check("test", "", "Names::Bar::TestObject") + % Check("test", "", "Bar::TestObject") % Check("test.[properties]", "<4 items>", "") % Check("test.[properties].myProp1", "\"Hello\"", "@QVariant (QString)") % Check("test.[properties].myProp2", "\"World\"", "@QVariant (QByteArray)") |