diff --git a/src/plugins/debugger/gdbengine.cpp b/src/plugins/debugger/gdbengine.cpp
index 16404d4276c057440b85384b9f40323edb24d9d5..5f524fc4f1192c6434221b8b13e80b7f055a3e47 100644
--- a/src/plugins/debugger/gdbengine.cpp
+++ b/src/plugins/debugger/gdbengine.cpp
@@ -148,6 +148,7 @@ enum GdbCommandType
     WatchDumpCustomSetup,
     WatchDumpCustomValue1,           // waiting for gdb ack
     WatchDumpCustomValue2,           // waiting for actual data
+    WatchDumpCustomValue3,           // macro based
     WatchDumpCustomEditValue,
 };
 
@@ -897,6 +898,11 @@ void GdbEngine::handleResult(const GdbResultRecord & record, int type,
         case WatchDumpCustomValue2:
             handleDumpCustomValue2(record, cookie.value<WatchData>());
             break;
+
+        case WatchDumpCustomValue3:
+            handleDumpCustomValue3(record, cookie.value<WatchData>());
+            break;
+
         case WatchDumpCustomSetup:
             handleDumpCustomSetup(record);
             break;
@@ -954,6 +960,30 @@ void GdbEngine::handleTargetCore(const GdbResultRecord &record)
     // Registers
     //
     qq->reloadRegisters();
+
+    // Gdb-Macro based Dumpers
+    sendCommand(
+        "define qdumpqstring\n"
+        "set $i = 0\n"
+        "set $l = $arg0->d->size\n"
+        "set $p = $arg0->d->data\n"
+        "while $i < $l\n"
+        "printf \"%d \",$p[$i++]\n"
+        "end\n"
+        "printf \"\\n\"\n"
+        "end\n"
+    );
+
+    sendCommand(
+        "define qdumpqstringlist\n"
+        "set $i = $arg0->d->begin\n"
+        "set $e = $arg0->d->end\n"
+        "while $i < $e\n"
+        "printf \"%d \",$arg0->d->array + $i++\n"
+        "end\n"
+        "printf \"\\n\"\n"
+        "end\n"
+    );
 }
 
 void GdbEngine::handleQueryPwd(const GdbResultRecord &record)
@@ -1613,6 +1643,9 @@ bool GdbEngine::startDebugger()
     sendCommand("set print elements 10000");
     sendCommand("-data-list-register-names", RegisterListNames);
 
+    sendCommand("set substitute-path /var/tmp/qt-x11-src-4.5.0 "
+        "/home/sandbox/qtsdk-2009.01/qt");
+
     // one of the following is needed to prevent crashes in gdb on code like:
     //  template <class T> T foo() { return T(0); }
     //  int main() { return foo<int>(); }
@@ -3041,6 +3074,13 @@ bool GdbEngine::isCustomValueDumperAvailable(const QString &type) const
     DebuggerSettings *s = q->settings();
     if (!s->m_useCustomDumpers)
         return false;
+
+    if (q->startMode() == AttachCore) {
+        // "call" is not possible in gdb when looking at core files
+        return type == "QString" || type.endsWith("::QString")
+            || type == "QStringList" || type.endsWith("::QStringList");
+    }
+
     if (s->m_debugDumpers && qq->stackHandler()->isDebuggingDumpers())
         return false;
     if (m_dataDumperState != DataDumperAvailable)
@@ -3058,8 +3098,32 @@ bool GdbEngine::isCustomValueDumperAvailable(const QString &type) const
     return m_availableSimpleDumpers.contains(tmplate);
 }
 
-void GdbEngine::runCustomDumper(const WatchData & data0, bool dumpChildren)
+void GdbEngine::runDirectDumper(const WatchData &data, bool dumpChildren)
 {
+    Q_UNUSED(dumpChildren);
+    QString type = data.type;
+    QString cmd;
+
+    if (type == "QString" || type.endsWith("::QString"))
+        cmd = "qdumpqstring (&" + data.exp + ")";
+    else if (type == "QStringList" || type.endsWith("::QStringList"))
+        cmd = "qdumpqstringlist (&" + data.exp + ")";
+
+    QVariant var;
+    var.setValue(data);
+    sendSynchronizedCommand(cmd, WatchDumpCustomValue3, var);
+
+    q->showStatusMessage(
+        tr("Retrieving data for watch view (%1 requests pending)...")
+            .arg(m_pendingRequests + 1), 10000);
+}
+
+void GdbEngine::runCustomDumper(const WatchData &data0, bool dumpChildren)
+{
+    if (q->startMode() == AttachCore) {
+        runDirectDumper(data0, dumpChildren);
+        return;
+    }
     WatchData data = data0;
     QTC_ASSERT(!data.exp.isEmpty(), return);
     QString tmplate;
@@ -3081,133 +3145,6 @@ void GdbEngine::runCustomDumper(const WatchData & data0, bool dumpChildren)
     extraArgs[1] = "0";
     extraArgs[2] = "0";
     extraArgs[3] = "0";
-    int extraArgCount = 0;
-
-    // "generic" template dumpers: passing sizeof(argument)
-    // gives already most information the dumpers need
-    foreach (const QString &arg, inners)
-        extraArgs[extraArgCount++] = sizeofTypeExpression(arg);
-
-    // in rare cases we need more or less:
-    if (outertype == m_namespace + "QObject") {
-        extraArgs[0] = "(char*)&((('"
-            + m_namespace + "QObjectPrivate'*)&"
-            + data.exp + ")->children)-(char*)&" + data.exp;
-    } else if (outertype == m_namespace + "QVector") {
-        extraArgs[1] = "(char*)&(("
-            + data.exp + ").d->array)-(char*)" + data.exp + ".d";
-    } else if (outertype == m_namespace + "QObjectSlot"
-            || outertype == m_namespace + "QObjectSignal") {
-        // we need the number out of something like
-        // iname="local.ob.slots.[2]deleteLater()"
-        int lastOpened = data.iname.lastIndexOf('[');
-        int lastClosed = data.iname.lastIndexOf(']');
-        QString slotNumber = "-1";
-        if (lastOpened != -1 && lastClosed != -1)
-            slotNumber = data.iname.mid(lastOpened + 1, lastClosed - lastOpened - 1);
-        extraArgs[0] = slotNumber;
-    } else if (outertype == m_namespace + "QMap" || outertype == m_namespace + "QMultiMap") {
-        QString nodetype;
-        if (m_qtVersion >= (4 << 16) + (5 << 8) + 0) {
-            nodetype  = m_namespace + "QMapNode";
-            nodetype += data.type.mid(outertype.size());
-        } else {
-            // FIXME: doesn't work for QMultiMap
-            nodetype  = data.type + "::Node";
-        }
-        //qDebug() << "OUTERTYPE: " << outertype << " NODETYPE: " << nodetype
-        //    << "QT VERSION" << m_qtVersion << ((4 << 16) + (5 << 8) + 0);
-        extraArgs[2] = sizeofTypeExpression(nodetype);
-        extraArgs[3] = "(size_t)&(('" + nodetype + "'*)0)->value";
-    } else if (outertype == m_namespace + "QMapNode") {
-        extraArgs[2] = sizeofTypeExpression(data.type);
-        extraArgs[3] = "(size_t)&(('" + data.type + "'*)0)->value";
-    } else if (outertype == "std::vector") {
-        //qDebug() << "EXTRACT TEMPLATE: " << outertype << inners;
-        if (inners.at(0) == "bool") {
-            outertype = "std::vector::bool";
-        } else {
-            //extraArgs[extraArgCount++] = sizeofTypeExpression(data.type);
-            //extraArgs[extraArgCount++] = "(size_t)&(('" + data.type + "'*)0)->value";
-        }
-    } else if (outertype == "std::deque") {
-        // remove 'std::allocator<...>':
-        extraArgs[1] = "0";
-    } else if (outertype == "std::stack") {
-        // remove 'std::allocator<...>':
-        extraArgs[1] = "0";
-    } 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.
-        // We read the type of the pair from the allocator argument because
-        // that gets the constness "right" (in the sense that gdb can
-        // read it back;
-        QString pairType = inners.at(3);
-        // remove 'std::allocator<...>':
-        pairType = pairType.mid(15, pairType.size() - 15 - 2);
-        extraArgs[2] = "(size_t)&(('" + pairType + "'*)0)->second";
-        extraArgs[3] = "0";
-    } else if (outertype == "std::basic_string") {
-        //qDebug() << "EXTRACT TEMPLATE: " << outertype << inners;
-        if (inners.at(0) == "char") {
-            outertype = "std::string";
-        } else if (inners.at(0) == "wchar_t") {
-            outertype = "std::wstring";
-        }
-        extraArgs[0] = "0";
-        extraArgs[1] = "0";
-        extraArgs[2] = "0";
-        extraArgs[3] = "0";
-    }
-
-    //int protocol = (data.iname.startsWith("watch") && data.type == "QImage") ? 3 : 2;
-    //int protocol = data.iname.startsWith("watch") ? 3 : 2;
-    int protocol = 2;
-    //int protocol = isDisplayedIName(data.iname) ? 3 : 2;
-
-    QString addr;
-    if (data.addr.startsWith("0x"))
-        addr = "(void*)" + data.addr;
-    else
-        addr = "&(" + data.exp + ")";
-
-    QByteArray params;
-    params.append(outertype.toUtf8());
-    params.append('\0');
-    params.append(data.iname.toUtf8());
-    params.append('\0');
-    params.append(data.exp.toUtf8());
-    params.append('\0');
-    params.append(inner.toUtf8());
-    params.append('\0');
-    params.append(data.iname.toUtf8());
-    params.append('\0');
-
-    sendWatchParameters(params);
-
-    QString cmd ="call "
-            + QString("qDumpObjectData440(")
-            + QString::number(protocol)
-            + ',' + "%1+1"                // placeholder for token
-            + ',' + addr
-            + ',' + (dumpChildren ? "1" : "0")
-            + ',' + extraArgs[0]
-            + ',' + extraArgs[1]
-            + ',' + extraArgs[2]
-            + ',' + extraArgs[3] + ')';
-
-    //qDebug() << "CMD: " << cmd;
-
-    QVariant var;
-    var.setValue(data);
-    sendSynchronizedCommand(cmd, WatchDumpCustomValue1, var);
-
-    q->showStatusMessage(
-        tr("Retrieving data for watch view (%1 requests pending)...")
-            .arg(m_pendingRequests + 1), 10000);
-
-    // retrieve response
-    sendSynchronizedCommand("p (char*)qDumpOutBuffer", WatchDumpCustomValue2, var);
 }
 
 void GdbEngine::createGdbVariable(const WatchData &data)
@@ -3722,6 +3659,56 @@ void GdbEngine::handleDumpCustomValue2(const GdbResultRecord &record,
     }
 }
 
+void GdbEngine::handleDumpCustomValue3(const GdbResultRecord &record,
+    const WatchData &data0)
+{
+    WatchData data = data0;
+    QByteArray out = record.data.findChild("consolestreamoutput").data();
+    while (out.endsWith(' ') || out.endsWith('\n'))
+        out.chop(1);
+    QList<QByteArray> list = out.split(' ');
+    //qDebug() << "RECEIVED" << record.toString() << " FOR " << data0.toString()
+    //    <<  " STREAM: " << out;
+    if (list.isEmpty()) {
+        data.setValue("<unavailable>");
+        data.setAllUnneeded();
+        insertData(data);
+    } else if (data.type == "QString" || data.type.endsWith("::QString")) {
+        QList<QByteArray> list = out.split(' ');
+        QString str;
+        for (int i = 0; i < list.size(); ++i)
+             str.append(list.at(i).toInt());
+        data.setValue('"' + str.toUtf8() + '"');
+        data.setChildCount(0);
+        data.setAllUnneeded();
+        insertData(data);
+    } else if (data.type == "QStringList" || data.type.endsWith("::QStringList")) {
+        int l = list.size();
+        data.setValue(QString("<%1 items>").arg(l).toLatin1());
+        data.setChildCount(list.size());
+        data.setAllUnneeded();
+        insertData(data);
+        for (int i = 0; i < l; ++i) {
+            WatchData data1;
+            data1.name = QString("[%1]").arg(i);
+            data1.type = data.type.left(data.type.size() - 4);
+            data1.iname = data.iname + QString(".%1").arg(i);
+            data1.addr = list.at(i);
+            data1.exp = "((" + gdbQuoteTypes(data1.type) + "*)" + data1.addr + ")";
+            data1.setChildCount(0);
+            data1.setValueNeeded();
+            QString cmd = "qdumpqstring (" + data1.exp + ")";
+            QVariant var;
+            var.setValue(data1);
+            sendSynchronizedCommand(cmd, WatchDumpCustomValue3, var);
+        }
+    } else {
+        data.setValue("<unavailable>");
+        data.setAllUnneeded();
+        insertData(data);
+    }
+}
+
 void GdbEngine::updateLocals()
 {
     m_pendingRequests = 0;
diff --git a/src/plugins/debugger/gdbengine.h b/src/plugins/debugger/gdbengine.h
index 661b8198accbd81a6ca3e61ff4ad95fb746e91c8..0205b1a862ddb61b12b030388fcd81c65cb4bcd8 100644
--- a/src/plugins/debugger/gdbengine.h
+++ b/src/plugins/debugger/gdbengine.h
@@ -305,6 +305,7 @@ private:
 
     void tryLoadCustomDumpers();
     void runCustomDumper(const WatchData &data, bool dumpChildren);
+    void runDirectDumper(const WatchData &data, bool dumpChildren);
     bool isCustomValueDumperAvailable(const QString &type) const;
 
     void handleVarListChildren(const GdbResultRecord &record,
@@ -316,12 +317,14 @@ private:
         const WatchData &cookie);
     void handleToolTip(const GdbResultRecord &record,
         const QString &cookie);
-    void handleDumpCustomValue1(const GdbResultRecord &record,
-        const WatchData &cookie);
     void handleQueryDataDumper1(const GdbResultRecord &record);
     void handleQueryDataDumper2(const GdbResultRecord &record);
+    void handleDumpCustomValue1(const GdbResultRecord &record,
+        const WatchData &cookie);
     void handleDumpCustomValue2(const GdbResultRecord &record,
         const WatchData &cookie);
+    void handleDumpCustomValue3(const GdbResultRecord &record,
+        const WatchData &cookie);
     void handleDumpCustomEditValue(const GdbResultRecord &record);
     void handleDumpCustomSetup(const GdbResultRecord &record);
     void handleStackListLocals(const GdbResultRecord &record);
diff --git a/tests/manual/gdbdebugger/simple/app.cpp b/tests/manual/gdbdebugger/simple/app.cpp
index 99f6ece6c52609ef49cf20b4f015dc44f6c8d8af..f4d92fc8233307f4a10db24c852196f21937e3f1 100644
--- a/tests/manual/gdbdebugger/simple/app.cpp
+++ b/tests/manual/gdbdebugger/simple/app.cpp
@@ -960,6 +960,9 @@ void testHidden()
 
 int main(int argc, char *argv[])
 {
+    QString hallo = "hallo";
+    QStringList list;
+    list << "aaa" << "bbb" << "cc";
     testIO();
     testHidden();
     testArray();