From 7898a499b6ecc1ac969c89ab134972a59de0bb9e Mon Sep 17 00:00:00 2001 From: hjk Date: Fri, 12 Dec 2008 12:55:05 +0100 Subject: [PATCH 1/5] add custom dumper for std::map --- bin/gdbmacros/gdbmacros.cpp | 64 +++++++++++++++++++++++-- src/plugins/debugger/gdbengine.cpp | 12 +++++ tests/manual/gdbdebugger/simple/app.cpp | 29 +++++++---- 3 files changed, 92 insertions(+), 13 deletions(-) diff --git a/bin/gdbmacros/gdbmacros.cpp b/bin/gdbmacros/gdbmacros.cpp index 9ea2a9aff56..ac10a4dde4f 100644 --- a/bin/gdbmacros/gdbmacros.cpp +++ b/bin/gdbmacros/gdbmacros.cpp @@ -123,6 +123,7 @@ int qtGhVersion = QT_VERSION; #endif #include +#include #include #include @@ -291,7 +292,7 @@ static bool startsWith(const char *s, const char *t) #define qCheckAccess(d) do { qProvokeSegFaultHelper = *(char*)d; } while (0) #define qCheckPointer(d) do { if (d) qProvokeSegFaultHelper = *(char*)d; } while (0) // provoke segfault unconditionally -#define qCheck(b) do { if (!b) qProvokeSegFaultHelper = *(char*)0; } while (0) +#define qCheck(b) do { if (!(b)) qProvokeSegFaultHelper = *(char*)0; } while (0) const char *stripNamespace(const char *type) { @@ -2146,6 +2147,61 @@ static void qDumpStdList(QDumper &d) d.disarm(); } +static void qDumpStdMap(QDumper &d) +{ + const std::map &map = + *reinterpret_cast *>(d.data); + const char *keyType = d.templateParameters[0]; + const char *valueType = d.templateParameters[1]; + const void *p = d.data; + qCheckAccess(p); + p = deref(p); + + int nn = map.size(); + qCheck(nn >= 0); + std::map::const_iterator it = map.begin(); + for (int i = 0; i < nn && i < 10 && it != map.end(); ++i, ++it) + qCheckAccess(it.operator->()); + + QByteArray strippedInnerType = stripPointerType(d.innertype); + P(d, "numchild", nn); + P(d, "value", "<" << nn << " items>"); + P(d, "valuedisabled", "true"); + P(d, "valueoffset", d.extraInt[2]); + + if (d.dumpChildren) { + bool simpleKey = isSimpleType(keyType); + bool simpleValue = isShortKey(valueType); + int valueOffset = d.extraInt[2]; + + d << ",children=["; + std::map::const_iterator it = map.begin(); + for (int i = 0; i < 1000 && it != map.end(); ++i, ++it) { + const void *node = it.operator->(); + if (simpleKey) { + d.beginHash(); + P(d, "type", valueType); + qDumpInnerValueHelper(d, keyType, node, "name"); + P(d, "nameisindex", "1"); + if (simpleValue) + qDumpInnerValueHelper(d, valueType, addOffset(node, valueOffset)); + P(d, "addr", addOffset(node, valueOffset)); + d.endHash(); + } else { + d.beginHash(); + P(d, "name", "[" << i << "]"); + P(d, "addr", it.operator->()); + P(d, "type", "std::pair"); + d.endHash(); + } + } + if (it != map.end()) + d.putEllipsis(); + d << "]"; + } + d.disarm(); +} + static void qDumpStdString(QDumper &d) { const std::string &str = *reinterpret_cast(d.data); @@ -2356,9 +2412,9 @@ static void handleProtocolVersion2and3(QDumper & d) qDumpStdVectorBool(d); else if (isEqual(type, "std::list")) qDumpStdList(d); - else if (isEqual(type, "string")) - qDumpStdString(d); - else if (isEqual(type, "std::string")) + else if (isEqual(type, "std::map")) + qDumpStdMap(d); + else if (isEqual(type, "std::string") || isEqual(type, "string")) qDumpStdString(d); else if (isEqual(type, "std::wstring")) qDumpStdWString(d); diff --git a/src/plugins/debugger/gdbengine.cpp b/src/plugins/debugger/gdbengine.cpp index 83473674782..5f7367b2e4c 100644 --- a/src/plugins/debugger/gdbengine.cpp +++ b/src/plugins/debugger/gdbengine.cpp @@ -2941,6 +2941,8 @@ bool GdbEngine::isCustomValueDumperAvailable(const QString &type) const } if (tmplate == "std::list") return true; + if (tmplate == "std::map") + return true; if (tmplate == "std::vector" && inner != "bool") return true; if (tmplate == "std::basic_string") { @@ -2962,6 +2964,8 @@ void GdbEngine::runCustomDumper(const WatchData & data0, bool dumpChildren) QStringList inners = inner.split('@'); if (inners.at(0).isEmpty()) inners.clear(); + for (int i = 0; i != inners.size(); ++i) + inners[i] = inners[i].simplified(); QString outertype = isTemplate ? tmplate : data.type; @@ -3015,6 +3019,12 @@ void GdbEngine::runCustomDumper(const WatchData & data0, bool dumpChildren) //extraArgs[extraArgCount++] = sizeofTypeExpression(data.type); //extraArgs[extraArgCount++] = "(size_t)&(('" + data.type + "'*)0)->value"; } + } else if (outertype == "std::map") { + // We don't want the comparator and the allocator confuse gdb. + // But we need the offset of the second item in the value pair. + extraArgs[2] = "(size_t)&(('std::pair'*)0)->second"; + extraArgs[3] = "0"; } else if (outertype == "std::basic_string") { //qDebug() << "EXTRACT TEMPLATE: " << outertype << inners; if (inners.at(0) == "char") { @@ -3064,6 +3074,8 @@ void GdbEngine::runCustomDumper(const WatchData & data0, bool dumpChildren) + ',' + extraArgs[2] + ',' + extraArgs[3] + ')'; + //qDebug() << "CMD: " << cmd; + sendSynchronizedCommand(cmd, WatchDumpCustomValue1, QVariant::fromValue(data)); q->showStatusMessage( diff --git a/tests/manual/gdbdebugger/simple/app.cpp b/tests/manual/gdbdebugger/simple/app.cpp index ab5ee635b5a..1eea659625d 100644 --- a/tests/manual/gdbdebugger/simple/app.cpp +++ b/tests/manual/gdbdebugger/simple/app.cpp @@ -267,7 +267,7 @@ void testQMap() ggt[11] = QStringList() << "11"; ggt[22] = QStringList() << "22"; -#if 0 +#if 1 QMap gg0; gg0[11] = 11.0; gg0[22] = 22.0; @@ -413,16 +413,31 @@ void testStdList() void testStdMap() { + std::map gg3; + gg3["22.0"] = Foo(22); + gg3["33.0"] = Foo(33); + gg3["44.0"] = Foo(44); + +#if 1 + std::map gg; + gg[11] = 1; + gg[22] = 2; + gg[33] = 3; + gg[44] = 4; + gg[55] = 5; + std::map ggl; ggl[11] = QStringList() << "11"; ggl[22] = QStringList() << "22"; + ggl[33] = QStringList() << "33"; + ggl[44] = QStringList() << "44"; + ggl[55] = QStringList() << "55"; typedef std::map T; T ggt; ggt[11] = QStringList() << "11"; ggt[22] = QStringList() << "22"; -#if 0 std::map gg0; gg0[11] = 11.0; gg0[22] = 22.0; @@ -434,15 +449,11 @@ void testStdMap() std::map gg2; gg2[22] = "22.0"; - std::map gg3; - gg3["22.0"] = Foo(22); - gg3["33.0"] = Foo(33); - QObject ob; std::map > map; - map.insert("Hallo", QPointer(&ob)); - map.insert("Welt", QPointer(&ob)); - map.insert(".", QPointer(&ob)); + map["Hallo"] = QPointer(&ob); + map["Welt"] = QPointer(&ob); + map["."] = QPointer(&ob); #endif } From 70d2bfed3263734d4db93c7a0e1bb9f02e43bfa2 Mon Sep 17 00:00:00 2001 From: hjk Date: Fri, 12 Dec 2008 13:02:29 +0100 Subject: [PATCH 2/5] code cosmetics on std::map dumper --- bin/gdbmacros/gdbmacros.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/bin/gdbmacros/gdbmacros.cpp b/bin/gdbmacros/gdbmacros.cpp index ac10a4dde4f..693830b0779 100644 --- a/bin/gdbmacros/gdbmacros.cpp +++ b/bin/gdbmacros/gdbmacros.cpp @@ -2149,8 +2149,8 @@ static void qDumpStdList(QDumper &d) static void qDumpStdMap(QDumper &d) { - const std::map &map = - *reinterpret_cast *>(d.data); + typedef std::map DummyType; + const DummyType &map = *reinterpret_cast(d.data); const char *keyType = d.templateParameters[0]; const char *valueType = d.templateParameters[1]; const void *p = d.data; @@ -2159,7 +2159,7 @@ static void qDumpStdMap(QDumper &d) int nn = map.size(); qCheck(nn >= 0); - std::map::const_iterator it = map.begin(); + DummyType::const_iterator it = map.begin(); for (int i = 0; i < nn && i < 10 && it != map.end(); ++i, ++it) qCheckAccess(it.operator->()); @@ -2175,7 +2175,7 @@ static void qDumpStdMap(QDumper &d) int valueOffset = d.extraInt[2]; d << ",children=["; - std::map::const_iterator it = map.begin(); + it = map.begin(); for (int i = 0; i < 1000 && it != map.end(); ++i, ++it) { const void *node = it.operator->(); if (simpleKey) { From 96c446ffd4df7db11582e8f631269e1332f878e6 Mon Sep 17 00:00:00 2001 From: hjk Date: Fri, 12 Dec 2008 13:09:34 +0100 Subject: [PATCH 3/5] remove some dead code --- bin/gdbmacros/gdbmacros.cpp | 29 +---------------------------- 1 file changed, 1 insertion(+), 28 deletions(-) diff --git a/bin/gdbmacros/gdbmacros.cpp b/bin/gdbmacros/gdbmacros.cpp index 693830b0779..a1b4e5afb84 100644 --- a/bin/gdbmacros/gdbmacros.cpp +++ b/bin/gdbmacros/gdbmacros.cpp @@ -2439,34 +2439,7 @@ void qDumpObjectData440( int extraInt2, int extraInt3) { - if (protocolVersion == -2) { - // close socket - QDumper d; - d.protocolVersion = protocolVersion; - d.token = token; - d.flush(); - d.disarm(); - } - - else if (protocolVersion == -1) { - // finalize Startup - QDumper d; - d.protocolVersion = protocolVersion; - d.token = token; - d.disarm(); - } - - else if (protocolVersion == 0) { - QDumper d; - d.protocolVersion = protocolVersion; - d.token = token; - // used to test whether error output gets through - //fprintf(stderr, "using stderr, qDebug follows: %d\n", token); - //qDebug() << "using qDebug, stderr already used: " << token; - d.disarm(); - } - - else if (protocolVersion == 1) { + if (protocolVersion == 1) { QDumper d; d.protocolVersion = protocolVersion; d.token = token; From 47c9f22f34a42d5e6b8252340ae90522d21168c3 Mon Sep 17 00:00:00 2001 From: hjk Date: Fri, 12 Dec 2008 13:14:51 +0100 Subject: [PATCH 4/5] remove dead code from dumpers --- bin/gdbmacros/gdbmacros.cpp | 17 +---------------- 1 file changed, 1 insertion(+), 16 deletions(-) diff --git a/bin/gdbmacros/gdbmacros.cpp b/bin/gdbmacros/gdbmacros.cpp index a1b4e5afb84..775819934bc 100644 --- a/bin/gdbmacros/gdbmacros.cpp +++ b/bin/gdbmacros/gdbmacros.cpp @@ -130,8 +130,6 @@ int qtGhVersion = QT_VERSION; #include #include -//#include - #ifdef Q_OS_WIN # include #endif @@ -173,9 +171,6 @@ public: // id of the thread that owns the object QThreadData *threadData; - void moveToThread_helper(); - void setThreadData_helper(QThreadData *currentData, QThreadData *targetData); - void _q_reregisterTimers(void *pointer); struct Sender { @@ -189,20 +184,12 @@ public: QList > eventFilters; - struct ExtraData - { -#ifndef QT_NO_USERDATA - QVector userData; -#endif - QList propertyNames; - QList propertyValues; - }; + struct ExtraData; ExtraData *extraData; mutable quint32 connectedSignals; QString objectName; - // Note: you must hold the signalSlotLock() before accessing the lists below or calling the functions struct Connection { QObject *receiver; @@ -215,8 +202,6 @@ public: QObjectConnectionListVector *connectionLists; QList senders; int *deleteWatch; - - static QObjectPrivate *get(QObject *o) { return o->d_func(); } }; #if defined(QT_BEGIN_NAMESPACE) From 1b325ce72176a7494f20a379bb60045a4c1dc349 Mon Sep 17 00:00:00 2001 From: Kavindra Palaraja Date: Fri, 12 Dec 2008 13:34:46 +0100 Subject: [PATCH 5/5] Fixes: Minor documentation changes --- doc/qtcreator.qdoc | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/doc/qtcreator.qdoc b/doc/qtcreator.qdoc index b8d38a60c9a..47022bb02d0 100644 --- a/doc/qtcreator.qdoc +++ b/doc/qtcreator.qdoc @@ -54,7 +54,7 @@ \o \l{Debugging with Qt Creator} \o \l{Tips and Tricks} \o \l{Glossary} - \o \l{Known Issues for Version 0.9 (Technical Preview)} + \o \l{Known Issues of Version 0.9 (Technical Preview)} \endlist */ @@ -577,7 +577,7 @@ \image qtcreator-navigate-customfilter.png - The following table gives an overview on the currently available filters: + The following table lists the filters currently available: \table \header @@ -1057,7 +1057,10 @@ \o Find Next \o F3 \row - \o Go back to Code Editor (May require more than one press) + \o Go back to Code Editor (\gui Edit mode: The first press gives + the editor focus, without closing secondary windows; the second + press closes all secondary windows. \gui Debug mode or \gui Help + mode: Switch to \gui Edit mode.) \o Esc \row \o Go to a Line @@ -1131,7 +1134,7 @@ The only solution for this problem is to boot another kernel. \o gdb sometimes takes very long to load debugging symbol, - especially from big libraries like libQtWebKit. Starting debugging + especially from big libraries like \c libQtWebKit. Starting debugging can take up to several minutes without visible progress. \o Paths or file names containing spaces or special characters like colons,