diff --git a/share/qtcreator/dumper/gbridge.py b/share/qtcreator/dumper/gbridge.py index 80bbd9e6fb1ae8b68e2f894edc9b4455c933e8a9..18f3eac73f0860d905631f851790827aa60c4ea3 100644 --- a/share/qtcreator/dumper/gbridge.py +++ b/share/qtcreator/dumper/gbridge.py @@ -1320,6 +1320,7 @@ class Dumper: self.formats = {} self.useDynamicType = True self.expandedINames = {} + self.childEventAddress = None def __init__(self, args): self.defaultInit() @@ -1571,18 +1572,36 @@ class Dumper: return self.dereference(value.address) def isQObject(self, value): - entryType = self.lookupType("int").pointer().pointer() try: - vtable = createReferenceValue(value, value.address, entryType) - metaObjectEntry = vtable.dereference() # It's the first entry. - return str(metaObjectEntry).find("::metaObject() const") > 0 + #if True: + vtable = self.dereference(long(value.address)) # + ptrSize + metaObjectEntry = self.dereference(vtable) # It's the first entry. + warn("MO: 0x%x " % metaObjectEntry) + s = gdb.execute("info symbol 0x%x" % metaObjectEntry, to_string=True) + warn("S: %s " % s) + #return s.find("::metaObject() const") > 0 + return s.find("::metaObject() const") > 0 or s.find("10metaObjectEv") > 0 + #return str(metaObjectEntry).find("::metaObject() const") > 0 except: return False + + def isQObject_B(self, value): # Alternative: Check for specific values, like targeting the # 'childEvent' member which is typically not overwritten, slot 8. - # entry = pointerValue(vtable) + 8 * ptrType.sizeof - # childEventEntry = createReferenceValue(value, entry, ptrType) - #warn("CHILDEVENT: %s " % childEventEntry) + # ~"Symbol \"Myns::QObject::childEvent(Myns::QChildEvent*)\" is a + # function at address 0xb70f691a.\n" + if self.childEventAddress == None: + try: + loc = gdb.execute("info address ::QObject::childEvent", to_string=True) + self.childEventAddress = long(loc[loc.rfind(' '):-2], 16) + except: + self.childEventAddress = 0 + + try: + vtable = self.dereference(long(value.address)) + return self.childEventAddress == self.dereference(vtable + 8 * self.ptrSize()) + except: + return False def put(self, value): self.output.append(value) diff --git a/share/qtcreator/dumper/qttypes.py b/share/qtcreator/dumper/qttypes.py index b7ad03ca533b2a625691161d6f0e58f9dd7bbc4b..af2422feb4b68385fa9c0b0579ae79bafd303dc7 100644 --- a/share/qtcreator/dumper/qttypes.py +++ b/share/qtcreator/dumper/qttypes.py @@ -51,11 +51,11 @@ def qByteArrayDataData(d, addr): # Data: # - QBasicAtomicInt ref; # - int alloc, size; + # - [padding] # - char *data; - # - char array[1]; alloc = d.extractInt(addr + intSize) size = d.extractInt(addr + 2 * intSize) - data = addr + 3 * intSize + ptrSize + data = d.dereference(addr + 2 * intSize + ptrSize) return data, size, alloc def qByteArrayData(d, addr): @@ -168,6 +168,7 @@ def qPutQObjectNameValue(d, value): objectName = d.dereference(extra + 5 * ptrSize) data, size, alloc = d.stringData(objectName) + if size > 0: str = d.readRawMemory(data, 2 * size) d.putValue(str, Hex4EncodedLittleEndian, 1) @@ -398,9 +399,17 @@ def qdump__QTime(d, value): # {sharedref(4), date(8), time(4+x)} def qdump__QDateTime(d, value): base = d.dereferenceValue(value) - mds = d.extractInt(base + d.ptrSize() + 8) + # QDateTimePrivate: + # - QAtomicInt ref; + # - [QDate date;] (+4) + # - - uint jd in Qt 4, qint64 in Qt 5 + # - [QTime time;] (+4 + dateSize) + # - - uint mds; + # - Spec spec; + dateSize = 8 if d.qtVersion() >= 0x050000 else 4 + mds = d.extractInt(base + 4 + dateSize) if mds >= 0: - jd = d.extractInt(base + d.ptrSize()) + jd = d.extractInt(base + 4) d.putValue("%s/%s" % (jd, mds), JulianDateAndMillisecondsSinceMidnight) d.putNumChild(1) if d.isExpanded(): @@ -412,12 +421,12 @@ def qdump__QDateTime(d, value): qtdate += "DateFormat::" # FIXME: Bug?... qttime += "TimeSpec::" # FIXME: Bug?... d.putCallItem("toTime_t", value, "toTime_t") - d.putCallItem("toString", value, "toString", qtdate + "TextDate") - d.putCallItem("(ISO)", value, "toString", qtdate + "ISODate") - d.putCallItem("(SystemLocale)", value, "toString", qtdate + "SystemLocaleDate") - d.putCallItem("(Locale)", value, "toString", qtdate + "LocaleDate") - d.putCallItem("toUTC", value, "toTimeSpec", qttime + "UTC") - d.putCallItem("toLocalTime", value, "toTimeSpec", qttime + "LocalTime") + #d.putCallItem("toString", value, "toString", qtdate + "TextDate") + #d.putCallItem("(ISO)", value, "toString", qtdate + "ISODate") + #d.putCallItem("(SystemLocale)", value, "toString", qtdate + "SystemLocaleDate") + #d.putCallItem("(Locale)", value, "toString", qtdate + "LocaleDate") + #d.putCallItem("toUTC", value, "toTimeSpec", qttime + "UTC") + #d.putCallItem("toLocalTime", value, "toTimeSpec", qttime + "LocalTime") else: d.putValue("(invalid)") d.putNumChild(0) @@ -1435,10 +1444,11 @@ def qdump__QObject(d, value): # } def qdump__QPixmap(d, value): - intPtrType = d.lookupType("int").pointer() - offset = (3 if d.qtVersion() >= 0x050000 else 2) * intPtrType.sizeof - base = d.createValue(d.addressOf(value) + offset, intPtrType) - d.putValue("(%dx%d)" % (base[1], base[2])) + offset = (3 if d.qtVersion() >= 0x050000 else 2) * d.ptrSize() + base = d.dereference(d.addressOf(value) + offset) + width = d.extractInt(base + 4) + height = d.extractInt(base + 8) + d.putValue("(%dx%d)" % (width, height)) d.putNumChild(0) diff --git a/tests/auto/debugger/tst_dumpers.cpp b/tests/auto/debugger/tst_dumpers.cpp index 9bb97778270ef8d80417b0fa9d5f442d02f610ba..227aa28c4c89eefc7b973f710b4ed4c9008002d4 100644 --- a/tests/auto/debugger/tst_dumpers.cpp +++ b/tests/auto/debugger/tst_dumpers.cpp @@ -545,9 +545,9 @@ private: void tst_Dumpers::initTestCase() { m_debuggerBinary = qgetenv("QTC_DEBUGGER_PATH_FOR_TEST"); - if (m_debuggerBinary.isEmpty()) m_debuggerBinary = "gdb"; + qDebug() << "Debugger : " << m_debuggerBinary.constData(); m_debuggerEngine = DumpTestGdbEngine; if (m_debuggerBinary.endsWith("cdb.exe")) @@ -559,6 +559,7 @@ void tst_Dumpers::initTestCase() m_qmakeBinary = qgetenv("QTC_QMAKE_PATH_FOR_TEST"); if (m_qmakeBinary.isEmpty()) m_qmakeBinary = "qmake"; + qDebug() << "QMake : " << m_qmakeBinary.constData(); Environment utilsEnv = Environment::systemEnvironment(); utilsEnv.appendOrSet(QLatin1String("QT_HASH_SEED"), QLatin1String("0")); @@ -574,8 +575,8 @@ void tst_Dumpers::initTestCase() QByteArray output = debugger.readAllStandardOutput(); //qDebug() << "stdout: " << output; m_usePython = !output.contains("Python scripting is not supported in this copy of GDB"); - qDebug() << (m_usePython ? "Python is available" : "Python is not available"); - qDebug() << "Dumper dir: " << DUMPERDIR; + qDebug() << "Python : " << (m_usePython ? "ok" : "*** not ok ***"); + qDebug() << "Dumper dir : " << DUMPERDIR; QString version = QString::fromLocal8Bit(output); int pos1 = version.indexOf(QLatin1String("&\"show version\\n")); @@ -587,7 +588,7 @@ void tst_Dumpers::initTestCase() version = version.mid(pos1, pos2 - pos1); extractGdbVersion(version, &m_gdbVersion, &m_gdbBuildVersion, &m_isMacGdb, &m_isQnxGdb); - qDebug() << "Gdb version " << m_gdbVersion; + qDebug() << "Gdb version : " << m_gdbVersion; } else if (m_debuggerEngine == DumpTestCdbEngine) { QByteArray envBat = qgetenv("QTC_MSVC_ENV_BAT"); QMap <QString, QString> envPairs; @@ -1116,20 +1117,23 @@ void tst_Dumpers::dumper_data() QTest::newRow("QDateTime0") << Data("#include <QDateTime>\n", - "QDateTime date;\n") + "QDateTime date;\n" + "unused(&date);\n") % CoreProfile() % Check("date", "(invalid)", "@QDateTime"); QTest::newRow("QDateTime1") << Data("#include <QDateTime>\n", - "QDateTime date(QDate(1980, 1, 1), QTime(13, 15, 32), Qt::UTC);\n") + "QDateTime date(QDate(1980, 1, 1), QTime(13, 15, 32), Qt::UTC);\n" + "unused(&date);\n") % CoreProfile() % Check("date", "Tue Jan 1 13:15:32 1980", "@QDateTime") - % Check("date.(ISO)", "\"1980-01-01T13:15:32Z\"", "@QString") - % CheckType("date.(Locale)", "@QString") - % CheckType("date.(SystemLocale)", "@QString") - % Check("date.toString", "\"Tue Jan 1 13:15:32 1980\"", "@QString") - % Check("date.toUTC", "Tue Jan 1 13:15:32 1980", "@QDateTime"); + //% Check("date.(ISO)", "\"1980-01-01T13:15:32Z\"", "@QString") + //% CheckType("date.(Locale)", "@QString") + //% CheckType("date.(SystemLocale)", "@QString") + //% Check("date.toString", "\"Tue Jan 1 13:15:32 1980\"", "@QString") + //% Check("date.toUTC", "Tue Jan 1 13:15:32 1980", "@QDateTime" + % Check("date.toTime_t", "315580532", "unsigned int"); #ifdef Q_OS_WIN QByteArray tempDir = "\"C:/Program Files\""; @@ -3111,16 +3115,17 @@ void tst_Dumpers::dumper_data() % Check("anc", "1", "int"); QTest::newRow("QThread1") - << Data("#include <QThread>\n", + << Data("#include <QThread>\n" "struct Thread : QThread\n" "{\n" + " virtual ~Thread() {}\n" " void run()\n" " {\n" " if (m_id == 3)\n" " breakHere();\n" " }\n" " int m_id;\n" - "};\n" + "};\n", "const int N = 14;\n" "Thread thread[N];\n" "for (int i = 0; i != N; ++i) {\n" @@ -3128,9 +3133,10 @@ void tst_Dumpers::dumper_data() " thread[i].setObjectName(\"This is thread #\" + QString::number(i));\n" " thread[i].start();\n" "}\n") - % CheckType("this", "Thread") - % Check("this.@1", "[@QThread]", "\"This is thread #3\"", "@QThread") - % Check("this.@1.@1", "[@QObject]", "\"This is thread #3\"", "@QObject"); + % CoreProfile() + % CheckType("this", "Thread") + % Check("this.@1", "[@QThread]", "\"This is thread #3\"", "@QThread") + % Check("this.@1.@1", "[@QObject]", "\"This is thread #3\"", "@QObject"); QTest::newRow("QVariant1") << Data("#include <QVariant>\n", @@ -3249,6 +3255,7 @@ void tst_Dumpers::dumper_data() "QVariant var;\n" "var.setValue(my);\n" "breakHere();\n") + % CoreProfile() % Check("my", "<2 items>", "MyType") % Check("my.0", "[0]", "", "@QMapNode<unsigned int, @QStringList>") % Check("my.0.key", "1", "unsigned int") @@ -3297,6 +3304,7 @@ void tst_Dumpers::dumper_data() "vl.append(QVariant(21));\n" "vl.append(QVariant(22));\n" "vl.append(QVariant(\"2Some String\"));\n") + % CoreProfile() % Check("vl", "<6 items>", "@QVariantList") % CheckType("vl.0", "[0]", "@QVariant (int)") % CheckType("vl.2", "[2]", "@QVariant (QString)"); @@ -3310,6 +3318,7 @@ void tst_Dumpers::dumper_data() "vm[\"d\"] = QVariant(21);\n" "vm[\"e\"] = QVariant(22);\n" "vm[\"f\"] = QVariant(\"2Some String\");\n") + % CoreProfile() % Check("vm", "<6 items>", "@QVariantMap") % Check("vm.0", "[0]", "", "@QMapNode<@QString, @QVariant>") % Check("vm.0.key", Value4("\"a\""), "@QString") @@ -3318,15 +3327,16 @@ void tst_Dumpers::dumper_data() % Check("vm.0.value", Value5("2"), "@QVariant (int)") % Check("vm.5", "[5]", "", "@QMapNode<@QString, @QVariant>") % Check("vm.5.key", Value4("\"f\""), "@QString") - % Check("vm.5.value", Value4("\"2Some String\""), "@QVariant (@QString)") + % Check("vm.5.value", Value4("\"2Some String\""), "@QVariant (QString)") % Check("vm.5.key", Value5("\"f\""), "@QString") - % Check("vm.5.value", Value5("\"2Some String\""), "@QVariant (@QString)"); + % Check("vm.5.value", Value5("\"2Some String\""), "@QVariant (QString)"); QTest::newRow("QVectorIntBig") << Data("#include <QVector>\n", "QVector<int> vec(10000);\n" "for (int i = 0; i != vec.size(); ++i)\n" " vec[i] = i * i;\n") + % CoreProfile() % Check("vec", "<10000 items>", "@QVector<int>") % Check("vec.0", "[0]", "0", "int") % Check("vec.1999", "[1999]", "3996001", "int"); @@ -3336,6 +3346,7 @@ void tst_Dumpers::dumper_data() "QVector<Foo> vec;\n" "vec.append(1);\n" "vec.append(2);\n") + % CoreProfile() % Check("vec", "<2 items>", "@QVector<Foo>") % Check("vec.0", "[0]", "", "Foo") % Check("vec.0.a", "1", "int") @@ -3348,7 +3359,8 @@ void tst_Dumpers::dumper_data() "FooVector vec;\n" "vec.append(1);\n" "vec.append(2);\n") - % Check("vec", "<2 items>", "@FooVector") + % CoreProfile() + % Check("vec", "<2 items>", "FooVector") % Check("vec.0", "[0]", "", "Foo") % Check("vec.0.a", "1", "int") % Check("vec.1", "[1]", "", "Foo") @@ -4025,7 +4037,7 @@ void tst_Dumpers::dumper_data() "boost::optional<QStringList> sl0, sl;\n" "sl = (QStringList() << \"xxx\" << \"yyy\");\n" "sl.get().append(\"zzz\");\n") - % Check("sl", "<3 items>", "boost::optional<QStringList>"); + % Check("sl", "<3 items>", "boost::optional<@QStringList>"); QTest::newRow("BoostSharedPtr") << Data("#include <QStringList>\n"