forked from qt-creator/qt-creator
Started on QObject dumping for CDB, make it smarter.
Try to find qobject_p.h, if it exists and use its structures to determine the child offset.
This commit is contained in:
@@ -32,6 +32,9 @@
|
||||
// this relies on contents copied from qobject_p.h
|
||||
#define PRIVATE_OBJECT_ALLOWED 1
|
||||
|
||||
#ifdef HAS_QOBJECT_P_H
|
||||
# include <QtCore/private/qobject_p.h>
|
||||
#endif
|
||||
#include <QtCore/QDateTime>
|
||||
#include <QtCore/QDebug>
|
||||
#include <QtCore/QDir>
|
||||
@@ -146,8 +149,7 @@ int qtGhVersion = QT_VERSION;
|
||||
# define NSY ""
|
||||
#endif
|
||||
|
||||
|
||||
#if PRIVATE_OBJECT_ALLOWED
|
||||
#if PRIVATE_OBJECT_ALLOWED && !HAS_QOBJECT_P_H
|
||||
|
||||
#if defined(QT_BEGIN_NAMESPACE)
|
||||
QT_BEGIN_NAMESPACE
|
||||
@@ -1532,6 +1534,13 @@ static void qDumpQObject(QDumper &d)
|
||||
const QObject *ob = reinterpret_cast<const QObject *>(d.data);
|
||||
const QMetaObject *mo = ob->metaObject();
|
||||
unsigned childrenOffset = d.extraInt[0];
|
||||
#ifdef HAS_QOBJECT_P_H
|
||||
// QObject child offset if known
|
||||
if (!childrenOffset) {
|
||||
QObjectPrivate qop;
|
||||
childrenOffset = (char*)&qop.children - (char*)&qop;
|
||||
}
|
||||
#endif
|
||||
P(d, "value", ob->objectName());
|
||||
P(d, "valueencoded", "2");
|
||||
P(d, "type", NS"QObject");
|
||||
@@ -1588,7 +1597,8 @@ static void qDumpQObject(QDumper &d)
|
||||
P(d, "numchild", slotCount);
|
||||
d.endHash();
|
||||
#endif
|
||||
d.beginHash();
|
||||
if (childrenOffset) {
|
||||
d.beginHash();
|
||||
P(d, "name", "children");
|
||||
// works always, but causes additional traffic on the list
|
||||
//P(d, "exp", "((class '"NS"QObject'*)" << d.data << ")->children()");
|
||||
@@ -1597,9 +1607,10 @@ static void qDumpQObject(QDumper &d)
|
||||
//P(d, "type", NS"QList<QObject *>");
|
||||
//P(d, "value", "<" << children.size() << " items>");
|
||||
qDumpInnerValue(d, NS"QList<"NS"QObject *>",
|
||||
addOffset(dfunc(ob), childrenOffset));
|
||||
addOffset(dfunc(ob), childrenOffset));
|
||||
P(d, "numchild", children.size());
|
||||
d.endHash();
|
||||
d.endHash();
|
||||
}
|
||||
#if 0
|
||||
// Unneeded (and not working): Connections are listes as childen
|
||||
// of the signal or slot they are connected to.
|
||||
|
@@ -5,3 +5,7 @@ CONFIG -= release
|
||||
CONFIG += debug
|
||||
}
|
||||
SOURCES=gdbmacros.cpp
|
||||
|
||||
exists($$QMAKE_INCDIR_QT/QtCore/private/qobject_p.h) {
|
||||
DEFINES+=HAS_QOBJECT_P_H
|
||||
}
|
||||
|
@@ -14,3 +14,8 @@ TEMPLATE = app
|
||||
|
||||
SOURCES += main.cpp \
|
||||
../gdbmacros.cpp
|
||||
|
||||
exists($$QMAKE_INCDIR_QT/QtCore/private/qobject_p.h) {
|
||||
DEFINES+=HAS_QOBJECT_P_H
|
||||
}
|
||||
|
||||
|
@@ -133,6 +133,17 @@ static int dumpStdString()
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int dumpStdWString()
|
||||
{
|
||||
std::wstring test = L"hallo";
|
||||
prepareInBuffer("std::wstring", "local.wstring", "local.wstring", "");
|
||||
qDumpObjectData440(2, 42, &test, 1, 0, 0, 0, 0);
|
||||
fputs(qDumpOutBuffer, stdout);
|
||||
fputc('\n', stdout);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int dumpStdStringList()
|
||||
{
|
||||
std::list<std::string> test;
|
||||
@@ -145,6 +156,18 @@ static int dumpStdStringList()
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int dumpStdStringQList()
|
||||
{
|
||||
QList<std::string> test;
|
||||
test.push_back("item1");
|
||||
test.push_back("item2");
|
||||
prepareInBuffer("QList", "local.stringqlist", "local.stringqlist", "std::string");
|
||||
qDumpObjectData440(2, 42, &test, 1, sizeof(std::string), 0, 0, 0);
|
||||
fputs(qDumpOutBuffer, stdout);
|
||||
fputc('\n', stdout);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int dumpStdIntList()
|
||||
{
|
||||
std::list<int> test;
|
||||
@@ -169,11 +192,28 @@ static int dumpStdIntVector()
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int dumpStdStringVector()
|
||||
{
|
||||
std::vector<std::string> test;
|
||||
test.push_back("item1");
|
||||
test.push_back("item2");
|
||||
prepareInBuffer("std::vector", "local.stringvector", "local.stringvector", "std::string");
|
||||
qDumpObjectData440(2, 42, &test, 1, sizeof(std::string), sizeof(std::list<int>::allocator_type), 0, 0);
|
||||
fputs(qDumpOutBuffer, stdout);
|
||||
fputc('\n', stdout);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int dumpQObject()
|
||||
{
|
||||
QTimer t;
|
||||
QObjectPrivate *tp = reinterpret_cast<QObjectPrivate *>(&t);
|
||||
#ifdef KNOWS_OFFSET
|
||||
const int childOffset = (char*)&tp->children - (char*)tp;
|
||||
#else
|
||||
const int childOffset = 0;
|
||||
#endif
|
||||
printf("Qt version %s Child offset: %d\n", QT_VERSION_STR, childOffset);
|
||||
prepareInBuffer("QObject", "local.qobject", "local.qobject", "");
|
||||
qDumpObjectData440(2, 42, &t, 1, childOffset, 0, 0, 0);
|
||||
@@ -200,16 +240,22 @@ int main(int argc, char *argv[])
|
||||
dumpQStringList();
|
||||
if (!qstrcmp(arg, "QList<int>"))
|
||||
dumpQIntList();
|
||||
if (!qstrcmp(arg, "QList<std::string>"))
|
||||
dumpStdStringQList();
|
||||
if (!qstrcmp(arg, "QVector<int>"))
|
||||
dumpQIntVector();
|
||||
if (!qstrcmp(arg, "string"))
|
||||
dumpStdString();
|
||||
if (!qstrcmp(arg, "wstring"))
|
||||
dumpStdWString();
|
||||
if (!qstrcmp(arg, "list<int>"))
|
||||
dumpStdIntList();
|
||||
if (!qstrcmp(arg, "list<string>"))
|
||||
dumpStdStringList();
|
||||
if (!qstrcmp(arg, "vector<int>"))
|
||||
dumpStdIntVector();
|
||||
if (!qstrcmp(arg, "vector<string>"))
|
||||
dumpStdStringVector();
|
||||
if (!qstrcmp(arg, "QObject"))
|
||||
dumpQObject();
|
||||
}
|
||||
|
@@ -367,7 +367,9 @@ QString decodeData(const QByteArray &ba, int encoding)
|
||||
// --------------- QtDumperResult
|
||||
|
||||
QtDumperResult::Child::Child() :
|
||||
valueEncoded(0)
|
||||
valueEncoded(0),
|
||||
childCount(0),
|
||||
valuedisabled(false)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -385,6 +387,7 @@ void QtDumperResult::clear()
|
||||
value.clear();
|
||||
address.clear();
|
||||
type.clear();
|
||||
displayedType.clear();
|
||||
valueEncoded = 0;
|
||||
valuedisabled = false;
|
||||
childCount = 0;
|
||||
@@ -403,7 +406,7 @@ QList<WatchData> QtDumperResult::toWatchData(int source) const
|
||||
const int lastDotIndex = root.iname.lastIndexOf(dot);
|
||||
root.exp = root.name = lastDotIndex == -1 ? iname : iname.mid(lastDotIndex + 1);
|
||||
root.setValue(decodeData(value, valueEncoded));
|
||||
root.setType(type);
|
||||
root.setType(displayedType.isEmpty() ? type : displayedType);
|
||||
root.valuedisabled = valuedisabled;
|
||||
root.setAddress(address);
|
||||
root.source = source;
|
||||
@@ -419,8 +422,10 @@ QList<WatchData> QtDumperResult::toWatchData(int source) const
|
||||
wchild.iname = iname;
|
||||
wchild.iname += dot;
|
||||
wchild.iname += dchild.name;
|
||||
wchild.exp = wchild.name = dchild.name;
|
||||
wchild.setType(childType);
|
||||
wchild.name = dchild.name;
|
||||
wchild.exp = dchild.exp;
|
||||
wchild.valuedisabled = dchild.valuedisabled;
|
||||
wchild.setType(dchild.type.isEmpty() ? childType : dchild.type);
|
||||
wchild.setAddress(dchild.address);
|
||||
wchild.setValue(decodeData(dchild.value, dchild.valueEncoded));
|
||||
wchild.setChildCount(0);
|
||||
@@ -436,19 +441,23 @@ QList<WatchData> QtDumperResult::toWatchData(int source) const
|
||||
QDebug operator<<(QDebug in, const QtDumperResult &d)
|
||||
{
|
||||
QDebug nospace = in.nospace();
|
||||
nospace << " iname=" << d.iname << " type=" << d.type << " address=" << d.address
|
||||
nospace << " iname=" << d.iname << " type=" << d.type << " displayed=" << d.displayedType
|
||||
<< " address=" << d.address
|
||||
<< " value=" << d.value
|
||||
<< " disabled=" << d.valuedisabled
|
||||
<< " encoded=" << d.valueEncoded << " internal=" << d.internal;
|
||||
if (d.childCount) {
|
||||
nospace << " childCount=" << d.childCount
|
||||
const int realChildCount = d.children.size();
|
||||
if (d.childCount || realChildCount) {
|
||||
nospace << " childCount=" << d.childCount << '/' << realChildCount
|
||||
<< " childType=" << d.childType << '\n';
|
||||
const int childCount = d.children.size();
|
||||
for (int i = 0; i < childCount; i++) {
|
||||
for (int i = 0; i < realChildCount; i++) {
|
||||
const QtDumperResult::Child &c = d.children.at(i);
|
||||
nospace << " #" << i << " addr=" << c.address
|
||||
<< " disabled=" << c.valuedisabled
|
||||
<< " type=" << c.type
|
||||
<< " name=" << c.name << " encoded=" << c.valueEncoded
|
||||
<< " value=" << c.value << '\n';
|
||||
<< " value=" << c.value
|
||||
<< "childcount=" << c.childCount << '\n';
|
||||
}
|
||||
}
|
||||
return in;
|
||||
@@ -602,8 +611,6 @@ QtDumperHelper::Type QtDumperHelper::specialType(QString s)
|
||||
bool QtDumperHelper::needsExpressionSyntax(Type t)
|
||||
{
|
||||
switch (t) {
|
||||
case QObjectType:
|
||||
case QWidgetType:
|
||||
case QObjectSlotType:
|
||||
case QObjectSignalType:
|
||||
case QMapType:
|
||||
@@ -1064,12 +1071,14 @@ void QtDumperHelper::evaluationParameters(const WatchData &data,
|
||||
switch (td.type) {
|
||||
case QObjectType:
|
||||
case QWidgetType:
|
||||
extraArgs[0] = QLatin1String("(char*)&((('");
|
||||
extraArgs[0] += m_qtNamespace;
|
||||
extraArgs[0] += QLatin1String("QObjectPrivate'*)&");
|
||||
extraArgs[0] += data.exp;
|
||||
extraArgs[0] += QLatin1String(")->children)-(char*)&");
|
||||
extraArgs[0] += data.exp;
|
||||
if (debugger == GdbDebugger) {
|
||||
extraArgs[0] = QLatin1String("(char*)&((('");
|
||||
extraArgs[0] += m_qtNamespace;
|
||||
extraArgs[0] += QLatin1String("QObjectPrivate'*)&");
|
||||
extraArgs[0] += data.exp;
|
||||
extraArgs[0] += QLatin1String(")->children)-(char*)&");
|
||||
extraArgs[0] += data.exp;
|
||||
}
|
||||
break;
|
||||
case QVectorType:
|
||||
extraArgs[1] = QLatin1String("(char*)&((");
|
||||
@@ -1201,13 +1210,16 @@ protected:
|
||||
|
||||
private:
|
||||
enum Mode { None, ExpectingIName, ExpectingAddress, ExpectingValue,
|
||||
ExpectingType, ExpectingInternal,
|
||||
ExpectingType, ExpectingDisplayedType, ExpectingInternal,
|
||||
ExpectingValueDisabled, ExpectingValueEncoded,
|
||||
ExpectingChildType, ExpectingChildCount,
|
||||
ExpectingCommonChildType, ExpectingChildCount,
|
||||
IgnoreNext,
|
||||
ChildModeStart,
|
||||
ExpectingChildren,ExpectingChildName, ExpectingChildAddress,
|
||||
ExpectingChildValue, ExpectingChildValueEncoded };
|
||||
ExpectingChildExpression, ExpectingChildType,
|
||||
ExpectingChildValue, ExpectingChildValueEncoded,
|
||||
ExpectingChildValueDisabled, ExpectingChildChildCount
|
||||
};
|
||||
|
||||
static inline Mode nextMode(Mode in, const char *keyword, int size);
|
||||
|
||||
@@ -1226,11 +1238,15 @@ ValueDumperParser::Mode ValueDumperParser::nextMode(Mode in, const char *keyword
|
||||
{
|
||||
// Careful with same prefix
|
||||
switch (size) {
|
||||
case 3:
|
||||
if (!qstrncmp(keyword, "exp", size))
|
||||
return ExpectingChildExpression;
|
||||
break;
|
||||
case 4:
|
||||
if (!qstrncmp(keyword, "addr", size))
|
||||
return in > ChildModeStart ? ExpectingChildAddress : ExpectingAddress;
|
||||
if (!qstrncmp(keyword, "type", size))
|
||||
return ExpectingType;
|
||||
return in > ChildModeStart ? ExpectingChildType : ExpectingType;
|
||||
if (!qstrncmp(keyword, "name", size))
|
||||
return ExpectingChildName;
|
||||
break;
|
||||
@@ -1244,13 +1260,13 @@ ValueDumperParser::Mode ValueDumperParser::nextMode(Mode in, const char *keyword
|
||||
if (!qstrncmp(keyword, "children", size))
|
||||
return ExpectingChildren;
|
||||
if (!qstrncmp(keyword, "numchild", size))
|
||||
return ExpectingChildCount;
|
||||
return in > ChildModeStart ? ExpectingChildChildCount : ExpectingChildCount;
|
||||
if (!qstrncmp(keyword, "internal", size))
|
||||
return ExpectingInternal;
|
||||
break;
|
||||
case 9:
|
||||
if (!qstrncmp(keyword, "childtype", size))
|
||||
return ExpectingChildType;
|
||||
return ExpectingCommonChildType;
|
||||
break;
|
||||
case 12:
|
||||
if (!qstrncmp(keyword, "valueencoded", size))
|
||||
@@ -1258,7 +1274,9 @@ ValueDumperParser::Mode ValueDumperParser::nextMode(Mode in, const char *keyword
|
||||
break;
|
||||
case 13:
|
||||
if (!qstrncmp(keyword, "valuedisabled", size))
|
||||
return ExpectingValueDisabled;
|
||||
return in > ChildModeStart ? ExpectingChildValueDisabled : ExpectingValueDisabled;
|
||||
if (!qstrncmp(keyword, "displayedtype", size))
|
||||
return ExpectingDisplayedType;
|
||||
if (!qstrncmp(keyword, "childnumchild", size))
|
||||
return IgnoreNext;
|
||||
break;
|
||||
@@ -1306,10 +1324,13 @@ bool ValueDumperParser::handleValue(const char *k, int size)
|
||||
case ExpectingType:
|
||||
m_result.type = QString::fromLatin1(valueBA);
|
||||
break;
|
||||
case ExpectingDisplayedType:
|
||||
m_result.displayedType = QString::fromLatin1(valueBA);
|
||||
break;
|
||||
case ExpectingInternal:
|
||||
m_result.internal = valueBA == "true";
|
||||
break;
|
||||
case ExpectingChildType:
|
||||
case ExpectingCommonChildType:
|
||||
m_result.childType = QString::fromLatin1(valueBA);
|
||||
break;
|
||||
case ExpectingChildCount:
|
||||
@@ -1327,9 +1348,21 @@ bool ValueDumperParser::handleValue(const char *k, int size)
|
||||
case ExpectingChildValue:
|
||||
m_result.children.back().value = valueBA;
|
||||
break;
|
||||
case ExpectingChildExpression:
|
||||
m_result.children.back().exp = QString::fromLatin1(valueBA);
|
||||
break;
|
||||
case ExpectingChildValueEncoded:
|
||||
m_result.children.back().valueEncoded = QString::fromLatin1(valueBA).toInt();
|
||||
break;
|
||||
case ExpectingChildValueDisabled:
|
||||
m_result.children.back().valuedisabled = valueBA == "true";
|
||||
break;
|
||||
case ExpectingChildType:
|
||||
m_result.children.back().type = QString::fromLatin1(valueBA);
|
||||
break;
|
||||
case ExpectingChildChildCount:
|
||||
m_result.children.back().childCount = QString::fromLatin1(valueBA).toInt();
|
||||
break;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
@@ -1340,6 +1373,9 @@ bool QtDumperHelper::parseValue(const char *data, QtDumperResult *r)
|
||||
if (!parser.run())
|
||||
return false;
|
||||
*r = parser.result();
|
||||
// Sanity
|
||||
if (r->childCount < r->children.size())
|
||||
r->childCount = r->children.size();
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@@ -76,8 +76,12 @@ struct QtDumperResult
|
||||
Child();
|
||||
|
||||
int valueEncoded;
|
||||
int childCount;
|
||||
bool valuedisabled;
|
||||
QString name;
|
||||
QString address;
|
||||
QString exp;
|
||||
QString type;
|
||||
QByteArray value;
|
||||
};
|
||||
|
||||
@@ -88,6 +92,7 @@ struct QtDumperResult
|
||||
QString iname;
|
||||
QString address;
|
||||
QString type;
|
||||
QString displayedType;
|
||||
QByteArray value;
|
||||
int valueEncoded;
|
||||
bool valuedisabled;
|
||||
|
Reference in New Issue
Block a user