diff --git a/src/plugins/debugger/gdb/classicgdbengine.cpp b/src/plugins/debugger/gdb/classicgdbengine.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..20f15288e2180d2d266bebcbe30893536f57b7e4
--- /dev/null
+++ b/src/plugins/debugger/gdb/classicgdbengine.cpp
@@ -0,0 +1,761 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** Commercial Usage
+**
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Nokia.
+**
+** GNU Lesser General Public License Usage
+**
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file.  Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#include "gdbengine.h"
+
+#include "abstractgdbadapter.h"
+#include "debuggeractions.h"
+#include "debuggerstringutils.h"
+
+#include "stackhandler.h"
+#include "watchhandler.h"
+
+#include <utils/qtcassert.h>
+
+#include <QtCore/QFile>
+#include <QtCore/QFileInfo>
+
+
+#define PRECONDITION QTC_ASSERT(!hasPython(), /**/)
+#define CB(callback) &GdbEngine::callback, STRINGIFY(callback)
+
+
+//#define DEBUG_PENDING  1
+//#define DEBUG_SUBITEM  1
+
+#if DEBUG_PENDING
+#   define PENDING_DEBUG(s) qDebug() << s
+#else
+#   define PENDING_DEBUG(s)
+#endif
+#define PENDING_DEBUGX(s) qDebug() << s
+
+namespace Debugger {
+namespace Internal {
+
+// reads a MI-encoded item frome the consolestream
+static bool parseConsoleStream(const GdbResponse &response, GdbMi *contents)
+{
+    GdbMi output = response.data.findChild("consolestreamoutput");
+    QByteArray out = output.data();
+
+    int markerPos = out.indexOf('"') + 1; // position of 'success marker'
+    if (markerPos == 0 || out.at(markerPos) == 'f') {  // 't' or 'f'
+        // custom dumper produced no output
+        return false;
+    }
+
+    out = out.mid(markerPos +  1);
+    out = out.left(out.lastIndexOf('"'));
+    // optimization: dumper output never needs real C unquoting
+    out.replace('\\', "");
+
+    contents->fromStringMultiple(out);
+    //qDebug() << "CONTENTS" << contents->toString(true);
+    return contents->isValid();
+}
+
+static double getDumperVersion(const GdbMi &contents)
+{
+    const GdbMi dumperVersionG = contents.findChild("dumperversion");
+    if (dumperVersionG.type() != GdbMi::Invalid) {
+        bool ok;
+        const double v = QString::fromAscii(dumperVersionG.data()).toDouble(&ok);
+        if (ok)
+            return v;
+    }
+    return 1.0;
+}
+
+
+void GdbEngine::updateLocalsClassic(const QVariant &cookie)
+{
+    PRECONDITION;
+    m_processedNames.clear();
+
+    //PENDING_DEBUG("\nRESET PENDING");
+    //m_toolTipCache.clear();
+    m_toolTipExpression.clear();
+    manager()->watchHandler()->beginCycle();
+
+    // Asynchronous load of injected library, initialize in first stop
+    if (m_dumperInjectionLoad && m_debuggingHelperState == DebuggingHelperLoadTried
+            && m_dumperHelper.typeCount() == 0
+            && inferiorPid() > 0)
+        tryQueryDebuggingHelpersClassic();
+
+    QByteArray level = QByteArray::number(currentFrame());
+    // '2' is 'list with type and value'
+    QByteArray cmd = "-stack-list-arguments 2 " + level + ' ' + level;
+    postCommand(cmd, WatchUpdate,
+        CB(handleStackListArgumentsClassic));
+    // '2' is 'list with type and value'
+    postCommand("-stack-list-locals 2", WatchUpdate,
+        CB(handleStackListLocalsClassic), cookie); // stage 2/2
+}
+
+static inline QString msgRetrievingWatchData(int pending)
+{
+    return GdbEngine::tr("Retrieving data for watch view (%n requests pending)...", 0, pending);
+}
+
+void GdbEngine::runDirectDebuggingHelperClassic(const WatchData &data, bool dumpChildren)
+{
+    Q_UNUSED(dumpChildren)
+    QByteArray type = data.type.toLatin1();
+    QByteArray 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);
+    postCommand(cmd, WatchUpdate, CB(handleDebuggingHelperValue3Classic), var);
+
+    showStatusMessage(msgRetrievingWatchData(m_pendingRequests + 1), 10000);
+}
+
+void GdbEngine::runDebuggingHelperClassic(const WatchData &data0, bool dumpChildren)
+{
+    PRECONDITION;
+    if (m_debuggingHelperState != DebuggingHelperAvailable) {
+        runDirectDebuggingHelperClassic(data0, dumpChildren);
+        return;
+    }
+    WatchData data = data0;
+
+    // Avoid endless loops created by faulty dumpers.
+    QByteArray processedName = QByteArray::number(dumpChildren) + '-' + data.iname;
+    if (m_processedNames.contains(processedName)) {
+        gdbInputAvailable(LogStatus,
+            _("<Breaking endless loop for " + data.iname + ">"));
+        data.setAllUnneeded();
+        data.setValue(_("<unavailable>"));
+        data.setHasChildren(false);
+        insertData(data);
+        return; 
+    }
+    m_processedNames.insert(processedName);
+
+    QByteArray params;
+    QStringList extraArgs;
+    const QtDumperHelper::TypeData td = m_dumperHelper.typeData(data0.type);
+    m_dumperHelper.evaluationParameters(data, td, QtDumperHelper::GdbDebugger, &params, &extraArgs);
+
+    //int protocol = (data.iname.startsWith("watch") && data.type == "QImage") ? 3 : 2;
+    //int protocol = data.iname.startsWith("watch") ? 3 : 2;
+    const int protocol = 2;
+    //int protocol = isDisplayedIName(data.iname) ? 3 : 2;
+
+    QByteArray addr;
+    if (data.addr.startsWith("0x"))
+        addr = "(void*)" + data.addr;
+    else if (data.exp.isEmpty()) // happens e.g. for QAbstractItem
+        addr = "0";
+    else
+        addr = "&(" + data.exp + ')';
+
+    sendWatchParameters(params);
+
+    QString cmd;
+    QTextStream(&cmd) << "call " << "(void*)qDumpObjectData440(" <<
+            protocol << ",0," <<  addr << ',' << (dumpChildren ? "1" : "0")
+            << ',' << extraArgs.join(QString(_c(','))) <<  ')';
+
+    postCommand(cmd.toLatin1(), WatchUpdate | NonCriticalResponse);
+
+    showStatusMessage(msgRetrievingWatchData(m_pendingRequests + 1), 10000);
+
+    // retrieve response
+    postCommand("p (char*)&qDumpOutBuffer", WatchUpdate,
+        CB(handleDebuggingHelperValue2Classic), qVariantFromValue(data));
+}
+
+void GdbEngine::createGdbVariableClassic(const WatchData &data)
+{
+    PRECONDITION;
+    if (data.iname == "local.flist.0") {
+        int i = 1;
+        Q_UNUSED(i);
+    }
+    postCommand("-var-delete \"" + data.iname + '"', WatchUpdate);
+    QByteArray exp = data.exp;
+    if (exp.isEmpty() && data.addr.startsWith("0x"))
+        exp = "*(" + gdbQuoteTypes(data.type).toLatin1() + "*)" + data.addr;
+    QVariant val = QVariant::fromValue<WatchData>(data);
+    postCommand("-var-create \"" + data.iname + "\" * \"" + exp + '"',
+        WatchUpdate, CB(handleVarCreate), val);
+}
+
+void GdbEngine::updateSubItemClassic(const WatchData &data0)
+{
+    PRECONDITION;
+    WatchData data = data0;
+    #if DEBUG_SUBITEM
+    qDebug() << "UPDATE SUBITEM:" << data.toString();
+    #endif
+    QTC_ASSERT(data.isValid(), return);
+
+    // in any case we need the type first
+    if (data.isTypeNeeded()) {
+        // This should only happen if we don't have a variable yet.
+        // Let's play safe, though.
+        if (!data.variable.isEmpty()) {
+            // Update: It does so for out-of-scope watchers.
+            #if 1
+            qDebug() << "FIXME: GdbEngine::updateSubItem:"
+                 << data.toString() << "should not happen";
+            #else
+            data.setType(WatchData::msgNotInScope());
+            data.setValue(WatchData::msgNotInScope());
+            data.setHasChildren(false);
+            insertData(data);
+            return;
+            #endif
+        }
+        // The WatchVarCreate handler will receive type information
+        // and re-insert a WatchData item with correct type, so
+        // we will not re-enter this bit.
+        // FIXME: Concurrency issues?
+        createGdbVariableClassic(data);
+        return;
+    }
+
+    // we should have a type now. this is relied upon further below
+    QTC_ASSERT(!data.type.isEmpty(), return);
+
+    // a common case that can be easily solved
+    if (data.isChildrenNeeded() && isPointerType(data.type)
+        && !hasDebuggingHelperForType(data.type)) {
+        // We sometimes know what kind of children pointers have
+        #if DEBUG_SUBITEM
+        qDebug() << "IT'S A POINTER";
+        #endif
+    
+        if (theDebuggerBoolSetting(AutoDerefPointers)) {
+            // Try automatic dereferentiation
+            data.exp = "(*(" + data.exp + "))";
+            data.type = data.type + _("."); // FIXME: fragile HACK to avoid recursion
+            insertData(data);
+        } else {
+            data.setChildrenUnneeded();
+            insertData(data);
+            WatchData data1;
+            data1.iname = data.iname + ".*";
+            data1.name = QLatin1Char('*') + data.name;
+            data1.exp = "(*(" + data.exp + "))";
+            data1.type = stripPointerType(data.type);
+            data1.setValueNeeded();
+            data1.setChildrenUnneeded();
+            insertData(data1);
+        }
+        return;
+    }
+
+    if (data.isValueNeeded() && hasDebuggingHelperForType(data.type)) {
+        #if DEBUG_SUBITEM
+        qDebug() << "UPDATE SUBITEM: CUSTOMVALUE";
+        #endif
+        runDebuggingHelperClassic(data,
+            manager()->watchHandler()->isExpandedIName(data.iname));
+        return;
+    }
+
+/*
+    if (data.isValueNeeded() && data.exp.isEmpty()) {
+        #if DEBUG_SUBITEM
+        qDebug() << "UPDATE SUBITEM: NO EXPRESSION?";
+        #endif
+        data.setError("<no expression given>");
+        insertData(data);
+        return;
+    }
+*/
+
+    if (data.isValueNeeded() && data.variable.isEmpty()) {
+        #if DEBUG_SUBITEM
+        qDebug() << "UPDATE SUBITEM: VARIABLE NEEDED FOR VALUE";
+        #endif
+        createGdbVariableClassic(data);
+        // the WatchVarCreate handler will re-insert a WatchData
+        // item, with valueNeeded() set.
+        return;
+    }
+
+    if (data.isValueNeeded()) {
+        QTC_ASSERT(!data.variable.isEmpty(), return); // tested above
+        #if DEBUG_SUBITEM
+        qDebug() << "UPDATE SUBITEM: VALUE";
+        #endif
+        QByteArray cmd = "-var-evaluate-expression \"" + data.iname + '"';
+        postCommand(cmd, WatchUpdate, CB(handleEvaluateExpression),
+            QVariant::fromValue(data));
+        return;
+    }
+
+    if (data.isChildrenNeeded() && hasDebuggingHelperForType(data.type)) {
+        #if DEBUG_SUBITEM
+        qDebug() << "UPDATE SUBITEM: CUSTOMVALUE WITH CHILDREN";
+        #endif
+        runDebuggingHelperClassic(data, true);
+        return;
+    }
+
+    if (data.isChildrenNeeded() && data.variable.isEmpty()) {
+        #if DEBUG_SUBITEM
+        qDebug() << "UPDATE SUBITEM: VARIABLE NEEDED FOR CHILDREN";
+        #endif
+        createGdbVariableClassic(data);
+        // the WatchVarCreate handler will re-insert a WatchData
+        // item, with childrenNeeded() set.
+        return;
+    }
+
+    if (data.isChildrenNeeded()) {
+        QTC_ASSERT(!data.variable.isEmpty(), return); // tested above
+        QByteArray cmd = "-var-list-children --all-values \"" + data.variable + '"';
+        postCommand(cmd, WatchUpdate, CB(handleVarListChildren), QVariant::fromValue(data));
+        return;
+    }
+
+    if (data.isHasChildrenNeeded() && hasDebuggingHelperForType(data.type)) {
+        #if DEBUG_SUBITEM
+        qDebug() << "UPDATE SUBITEM: CUSTOMVALUE WITH CHILDREN";
+        #endif
+        runDebuggingHelperClassic(data,
+            manager()->watchHandler()->isExpandedIName(data.iname));
+        return;
+    }
+
+//#if !X
+    if (data.isHasChildrenNeeded() && data.variable.isEmpty()) {
+        #if DEBUG_SUBITEM
+        qDebug() << "UPDATE SUBITEM: VARIABLE NEEDED FOR CHILDCOUNT";
+        #endif
+        createGdbVariableClassic(data);
+        // the WatchVarCreate handler will re-insert a WatchData
+        // item, with childrenNeeded() set.
+        return;
+    }
+//#endif
+
+    if (data.isHasChildrenNeeded()) {
+        QTC_ASSERT(!data.variable.isEmpty(), return); // tested above
+        QByteArray cmd = "-var-list-children --all-values \"" + data.variable + '"';
+        postCommand(cmd, Discardable,
+            CB(handleVarListChildren), QVariant::fromValue(data));
+        return;
+    }
+
+    qDebug() << "FIXME: UPDATE SUBITEM:" << data.toString();
+    QTC_ASSERT(false, return);
+}
+
+void GdbEngine::handleDebuggingHelperValue2Classic(const GdbResponse &response)
+{
+    PRECONDITION;
+    WatchData data = response.cookie.value<WatchData>();
+    QTC_ASSERT(data.isValid(), return);
+
+    // The real dumper might have aborted without giving any answers.
+    // Remove traces of the question, too.
+    if (m_cookieForToken.contains(response.token - 1)) {
+        m_cookieForToken.remove(response.token - 1);
+        debugMessage(_("DETECTING LOST COMMAND %1").arg(response.token - 1));
+        --m_pendingRequests;
+        data.setError(WatchData::msgNotInScope());
+        insertData(data);
+        return;
+    }
+
+    //qDebug() << "CUSTOM VALUE RESULT:" << response.toString();
+    //qDebug() << "FOR DATA:" << data.toString() << response.resultClass;
+    if (response.resultClass != GdbResultDone) {
+        qDebug() << "STRANGE CUSTOM DUMPER RESULT DATA:" << data.toString();
+        return;
+    }
+
+    GdbMi contents;
+    if (!parseConsoleStream(response, &contents)) {
+        data.setError(WatchData::msgNotInScope());
+        insertData(data);
+        return;
+    }
+
+    setWatchDataType(data, response.data.findChild("type"));
+    setWatchDataDisplayedType(data, response.data.findChild("displaytype"));
+    QList<WatchData> list;
+    handleChildren(data, contents, &list);
+    //for (int i = 0; i != list.size(); ++i)
+    //    qDebug() << "READ: " << list.at(i).toString();
+    manager()->watchHandler()->insertBulkData(list);
+}
+
+void GdbEngine::handleDebuggingHelperValue3Classic(const GdbResponse &response)
+{
+    if (response.resultClass == GdbResultDone) {
+        WatchData data = response.cookie.value<WatchData>();
+        QByteArray out = response.data.findChild("consolestreamoutput").data();
+        while (out.endsWith(' ') || out.endsWith('\n'))
+            out.chop(1);
+        QList<QByteArray> list = out.split(' ');
+        //qDebug() << "RECEIVED" << response.toString() << "FOR" << data0.toString()
+        //    <<  " STREAM:" << out;
+        if (list.isEmpty()) {
+            //: Value for variable
+            data.setError(WatchData::msgNotInScope());
+            data.setAllUnneeded();
+            insertData(data);
+        } else if (data.type == __("QString")
+                || data.type.endsWith(__("::QString"))) {
+            QList<QByteArray> list = out.split(' ');
+            QString str;
+            int l = out.isEmpty() ? 0 : list.size();
+            for (int i = 0; i < l; ++i)
+                 str.append(list.at(i).toInt());
+            data.setValue(_c('"') + str + _c('"'));
+            data.setHasChildren(false);
+            data.setAllUnneeded();
+            insertData(data);
+        } else if (data.type == __("QStringList")
+                || data.type.endsWith(__("::QStringList"))) {
+            if (out.isEmpty()) {
+                data.setValue(tr("<0 items>"));
+                data.setHasChildren(false);
+                data.setAllUnneeded();
+                insertData(data);
+            } else {
+                int l = list.size();
+                //: In string list
+                data.setValue(tr("<%n items>", 0, l));
+                data.setHasChildren(!list.empty());
+                data.setAllUnneeded();
+                insertData(data);
+                for (int i = 0; i < l; ++i) {
+                    WatchData data1;
+                    data1.name = _("[%1]").arg(i);
+                    data1.type = data.type.left(data.type.size() - 4);
+                    data1.iname = data.iname + '.' + QByteArray::number(i);
+                    data1.addr = list.at(i);
+                    data1.exp = "((" + gdbQuoteTypes(data1.type).toLatin1() + "*)" + data1.addr + ")";
+                    data1.setHasChildren(false);
+                    data1.setValueNeeded();
+                    QByteArray cmd = "qdumpqstring (" + data1.exp + ')';
+                    QVariant var;
+                    var.setValue(data1);
+                    postCommand(cmd, WatchUpdate,
+                        CB(handleDebuggingHelperValue3Classic), var);
+                }
+            }
+        } else {
+            //: Value for variable
+            data.setError(WatchData::msgNotInScope());
+            data.setAllUnneeded();
+            insertData(data);
+        }
+    } else {
+        WatchData data = response.cookie.value<WatchData>();
+        data.setError(WatchData::msgNotInScope());
+        data.setAllUnneeded();
+        insertData(data);
+    }
+}
+
+void GdbEngine::tryLoadDebuggingHelpersClassic()
+{
+    PRECONDITION;
+    if (isSynchroneous())
+        return;
+    switch (m_debuggingHelperState) {
+    case DebuggingHelperUninitialized:
+        break;
+    case DebuggingHelperLoadTried:
+        tryQueryDebuggingHelpersClassic();
+        return;
+    case DebuggingHelperAvailable:
+    case DebuggingHelperUnavailable:
+        return;
+    }
+
+    if (m_gdbAdapter->dumperHandling() == AbstractGdbAdapter::DumperNotAvailable) {
+        // Load at least gdb macro based dumpers.
+        QFile file(_(":/gdb/gdbmacros.txt"));
+        file.open(QIODevice::ReadOnly);
+        QByteArray contents = file.readAll(); 
+        m_debuggingHelperState = DebuggingHelperLoadTried;
+        postCommand(contents);
+        return;
+    }
+    if (m_dumperInjectionLoad && inferiorPid() <= 0) // Need PID to inject
+        return;
+
+    PENDING_DEBUG("TRY LOAD CUSTOM DUMPERS");
+    m_debuggingHelperState = DebuggingHelperUnavailable;
+    if (!checkDebuggingHelpersClassic())
+        return;
+
+    m_debuggingHelperState = DebuggingHelperLoadTried;
+    QByteArray dlopenLib;
+    if (startParameters().startMode == StartRemote)
+        dlopenLib = startParameters().remoteDumperLib.toLocal8Bit();
+    else
+        dlopenLib = manager()->qtDumperLibraryName().toLocal8Bit();
+#if defined(Q_OS_WIN)
+    if (m_dumperInjectionLoad) {
+        /// Launch asynchronous remote thread to load.
+        SharedLibraryInjector injector(inferiorPid());
+        QString errorMessage;
+        const QString dlopenLibString = _(dlopenLib);
+        if (injector.remoteInject(dlopenLibString, false, &errorMessage)) {
+            debugMessage(_("Dumper injection loading triggered (%1)...").
+                         arg(dlopenLibString));
+        } else {
+            debugMessage(_("Dumper loading (%1) failed: %2").
+                         arg(dlopenLibString, errorMessage));
+            debugMessage(errorMessage);
+            manager()->showQtDumperLibraryWarning(errorMessage);
+            m_debuggingHelperState = DebuggingHelperUnavailable;
+            return;
+        }
+    } else {
+        debugMessage(_("Loading dumpers via debugger call (%1)...").
+                     arg(_(dlopenLib)));
+        postCommand("sharedlibrary .*"); // for LoadLibraryA
+        //postCommand("handle SIGSEGV pass stop print");
+        //postCommand("set unwindonsignal off");
+        postCommand("call LoadLibraryA(\"" + GdbMi::escapeCString(dlopenLib) + "\")",
+                    CB(handleDebuggingHelperSetup));
+        postCommand("sharedlibrary " + dotEscape(dlopenLib));
+    }
+#elif defined(Q_OS_MAC)
+    //postCommand("sharedlibrary libc"); // for malloc
+    //postCommand("sharedlibrary libdl"); // for dlopen
+    postCommand("call (void)dlopen(\"" + GdbMi::escapeCString(dlopenLib)
+                + "\", " STRINGIFY(RTLD_NOW) ")",
+        CB(handleDebuggingHelperSetup));
+    //postCommand("sharedlibrary " + dotEscape(dlopenLib));
+#else
+    //postCommand("p dlopen");
+    postCommand("sharedlibrary libc"); // for malloc
+    postCommand("sharedlibrary libdl"); // for dlopen
+    postCommand("call (void*)dlopen(\"" + GdbMi::escapeCString(dlopenLib)
+                + "\", " STRINGIFY(RTLD_NOW) ")",
+        CB(handleDebuggingHelperSetup));
+    // some older systems like CentOS 4.6 prefer this:
+    postCommand("call (void*)__dlopen(\"" + GdbMi::escapeCString(dlopenLib)
+                + "\", " STRINGIFY(RTLD_NOW) ")",
+        CB(handleDebuggingHelperSetup));
+    postCommand("sharedlibrary " + dotEscape(dlopenLib));
+#endif
+    if (!m_dumperInjectionLoad)
+        tryQueryDebuggingHelpersClassic();
+}
+
+void GdbEngine::tryQueryDebuggingHelpersClassic()
+{
+    PRECONDITION;
+    // retrieve list of dumpable classes
+    postCommand("call (void*)qDumpObjectData440(1,0,0,0,0,0,0,0)");
+    postCommand("p (char*)&qDumpOutBuffer",
+        CB(handleQueryDebuggingHelperClassic));
+}
+
+void GdbEngine::recheckDebuggingHelperAvailabilityClassic()
+{
+    PRECONDITION;
+    if (m_gdbAdapter->dumperHandling() != AbstractGdbAdapter::DumperNotAvailable) {
+        // retrieve list of dumpable classes
+        postCommand("call (void*)qDumpObjectData440(1,0,0,0,0,0,0,0)");
+        postCommand("p (char*)&qDumpOutBuffer",
+            CB(handleQueryDebuggingHelperClassic));
+    }
+}
+
+// Called from CoreAdapter and AttachAdapter
+void GdbEngine::updateAllClassic()
+{
+    PRECONDITION;
+    PENDING_DEBUG("UPDATING ALL\n");
+    QTC_ASSERT(state() == InferiorUnrunnable || state() == InferiorStopped, /**/);
+    tryLoadDebuggingHelpersClassic();
+    reloadModulesInternal();
+    postCommand("-stack-list-frames", WatchUpdate,
+        CB(handleStackListFrames),
+        QVariant::fromValue<StackCookie>(StackCookie(false, true)));
+    manager()->stackHandler()->setCurrentIndex(0);
+    if (supportsThreads())
+        postCommand("-thread-list-ids", WatchUpdate, CB(handleStackListThreads), 0);
+    manager()->reloadRegisters();
+    updateLocals(); 
+}
+
+void GdbEngine::setDebugDebuggingHelpersClassic(const QVariant &on)
+{
+    PRECONDITION;
+    if (on.toBool()) {
+        debugMessage(_("SWITCHING ON DUMPER DEBUGGING"));
+        postCommand("set unwindonsignal off");
+        m_manager->breakByFunction(_("qDumpObjectData440"));
+        //updateLocals();
+    } else {
+        debugMessage(_("SWITCHING OFF DUMPER DEBUGGING"));
+        postCommand("set unwindonsignal on");
+    }
+}
+
+void GdbEngine::setDebuggingHelperStateClassic(DebuggingHelperState s)
+{
+    PRECONDITION;
+    m_debuggingHelperState = s;
+}
+
+
+void GdbEngine::handleStackListArgumentsClassic(const GdbResponse &response)
+{
+    PRECONDITION;
+    // stage 1/2
+
+    // Linux:
+    // 12^done,stack-args=
+    //   [frame={level="0",args=[
+    //     {name="argc",type="int",value="1"},
+    //     {name="argv",type="char **",value="(char **) 0x7..."}]}]
+    // Mac:
+    // 78^done,stack-args=
+    //    {frame={level="0",args={
+    //      varobj=
+    //        {exp="this",value="0x38a2fab0",name="var21",numchild="3",
+    //             type="CurrentDocumentFind *  const",typecode="PTR",
+    //             dynamic_type="",in_scope="true",block_start_addr="0x3938e946",
+    //             block_end_addr="0x3938eb2d"},
+    //      varobj=
+    //         {exp="before",value="@0xbfffb9f8: {d = 0x3a7f2a70}",
+    //              name="var22",numchild="1",type="const QString  ...} }}}
+    //
+    // In both cases, iterating over the children of stack-args/frame/args
+    // is ok.
+    m_currentFunctionArgs.clear();
+    if (response.resultClass == GdbResultDone) {
+        const GdbMi list = response.data.findChild("stack-args");
+        const GdbMi frame = list.findChild("frame");
+        const GdbMi args = frame.findChild("args");
+        m_currentFunctionArgs = args.children();
+    } else {
+        qDebug() << "FIXME: GdbEngine::handleStackListArguments: should not happen"
+            << response.toString();
+    }
+}
+
+void GdbEngine::handleStackListLocalsClassic(const GdbResponse &response)
+{
+    PRECONDITION;
+    // stage 2/2
+
+    // There could be shadowed variables
+    QList<GdbMi> locals = response.data.findChild("locals").children();
+    locals += m_currentFunctionArgs;
+    QMap<QByteArray, int> seen;
+    // If desired, retrieve list of uninitialized variables looking at
+    // the current frame. This is invoked first time after a stop from
+    // handleStop1, which passes on the frame as cookie. The whole stack
+    // is not known at this point.
+    QStringList uninitializedVariables;
+    if (theDebuggerAction(UseCodeModel)->isChecked()) {
+        const StackFrame frame = qVariantCanConvert<Debugger::Internal::StackFrame>(response.cookie) ?
+                                 qVariantValue<Debugger::Internal::StackFrame>(response.cookie) :
+                                 m_manager->stackHandler()->currentFrame();
+        if (frame.isUsable())
+            getUninitializedVariables(m_manager->cppCodeModelSnapshot(),
+                                      frame.function, frame.file, frame.line,
+                                      &uninitializedVariables);
+    }
+    QList<WatchData> list;
+    foreach (const GdbMi &item, locals) {
+        const WatchData data = localVariable(item, uninitializedVariables, &seen);
+        if (data.isValid())
+            list.push_back(data);
+    }
+    manager()->watchHandler()->insertBulkData(list);
+    manager()->watchHandler()->updateWatchers();
+}
+
+bool GdbEngine::checkDebuggingHelpersClassic()
+{
+    PRECONDITION;
+    if (!manager()->qtDumperLibraryEnabled())
+        return false;
+    const QString lib = qtDumperLibraryName();
+    //qDebug() << "DUMPERLIB:" << lib;
+    const QFileInfo fi(lib);
+    if (!fi.exists()) {
+        const QStringList &locations = manager()->qtDumperLibraryLocations();
+        const QString loc = locations.join(QLatin1String(", "));
+        const QString msg = tr("The debugging helper library was not found at %1.").arg(loc);
+        debugMessage(msg);
+        manager()->showQtDumperLibraryWarning(msg);
+        return false;
+    }
+    return true;
+}
+
+void GdbEngine::handleQueryDebuggingHelperClassic(const GdbResponse &response)
+{
+    const double dumperVersionRequired = 1.0;
+    //qDebug() << "DATA DUMPER TRIAL:" << response.toString();
+
+    GdbMi contents;
+    QTC_ASSERT(parseConsoleStream(response, &contents), qDebug() << response.toString());
+    const bool ok = m_dumperHelper.parseQuery(contents, QtDumperHelper::GdbDebugger)
+        && m_dumperHelper.typeCount();
+    if (ok) {
+        // Get version and sizes from dumpers. Expression cache
+        // currently causes errors.
+        const double dumperVersion = getDumperVersion(contents);
+        if (dumperVersion < dumperVersionRequired) {
+            manager()->showQtDumperLibraryWarning(
+                QtDumperHelper::msgDumperOutdated(dumperVersionRequired, dumperVersion));
+            m_debuggingHelperState = DebuggingHelperUnavailable;
+            return;
+        }
+        m_debuggingHelperState = DebuggingHelperAvailable;
+        const QString successMsg = tr("Dumper version %1, %n custom dumpers found.",
+            0, m_dumperHelper.typeCount()).arg(dumperVersion);
+        showStatusMessage(successMsg);
+    } else {
+        if (!m_dumperInjectionLoad) // Retry if thread has not terminated yet.
+            m_debuggingHelperState = DebuggingHelperUnavailable;
+        showStatusMessage(tr("Debugging helpers not found."));
+    }
+    //qDebug() << m_dumperHelper.toString(true);
+    //qDebug() << m_availableSimpleDebuggingHelpers << "DATA DUMPERS AVAILABLE";
+}
+} // namespace Internal
+} // namespace Debugger
diff --git a/src/plugins/debugger/gdb/gdb.pri b/src/plugins/debugger/gdb/gdb.pri
index 1c969a42b8235bee254fe61e0da5b7328aec68ab..ad27702938604e28c495353983d4f31f370f70ab 100644
--- a/src/plugins/debugger/gdb/gdb.pri
+++ b/src/plugins/debugger/gdb/gdb.pri
@@ -19,6 +19,8 @@ HEADERS += \
 SOURCES += \
     $$PWD/gdbmi.cpp \
     $$PWD/gdbengine.cpp \
+    $$PWD/classicgdbengine.cpp \
+    $$PWD/pythongdbengine.cpp \
     $$PWD/gdboptionspage.cpp \
     $$PWD/trkoptions.cpp \
     $$PWD/trkoptionswidget.cpp \
diff --git a/src/plugins/debugger/gdb/gdbengine.cpp b/src/plugins/debugger/gdb/gdbengine.cpp
index 0379837e408ddd6382839403c424a29b8f1b30b8..7d25d9d00d95d95248821fe261c2e87a7de9ef4f 100644
--- a/src/plugins/debugger/gdb/gdbengine.cpp
+++ b/src/plugins/debugger/gdb/gdbengine.cpp
@@ -90,11 +90,18 @@
 #endif
 #include <ctype.h>
 
+#define DIVERT(func, pars) \
+    do { \
+        if (hasPython()) \
+            func ## Python(pars); \
+        else \
+            func ## Plain(pars); \
+    } while (0)
+
 namespace Debugger {
 namespace Internal {
 
 //#define DEBUG_PENDING  1
-//#define DEBUG_SUBITEM  1
 
 #if DEBUG_PENDING
 #   define PENDING_DEBUG(s) qDebug() << s
@@ -105,7 +112,7 @@ namespace Internal {
 
 #define CB(callback) &GdbEngine::callback, STRINGIFY(callback)
 
-static QByteArray tooltipINameForExpression(const QByteArray &exp)
+QByteArray GdbEngine::tooltipINameForExpression(const QByteArray &exp)
 {
     // FIXME: 'exp' can contain illegal characters
     //return "tooltip." + exp;
@@ -153,28 +160,6 @@ static bool isAccessSpecifier(const QByteArray &ba)
 }
 
 
-// reads a MI-encoded item frome the consolestream
-static bool parseConsoleStream(const GdbResponse &response, GdbMi *contents)
-{
-    GdbMi output = response.data.findChild("consolestreamoutput");
-    QByteArray out = output.data();
-
-    int markerPos = out.indexOf('"') + 1; // position of 'success marker'
-    if (markerPos == 0 || out.at(markerPos) == 'f') {  // 't' or 'f'
-        // custom dumper produced no output
-        return false;
-    }
-
-    out = out.mid(markerPos +  1);
-    out = out.left(out.lastIndexOf('"'));
-    // optimization: dumper output never needs real C unquoting
-    out.replace('\\', "");
-
-    contents->fromStringMultiple(out);
-    //qDebug() << "CONTENTS" << contents->toString(true);
-    return contents->isValid();
-}
-
 static QByteArray parsePlainConsoleStream(const GdbResponse &response)
 {
     GdbMi output = response.data.findChild("consolestreamoutput");
@@ -276,7 +261,7 @@ void GdbEngine::initializeVariables()
     m_gdbVersion = 100;
     m_gdbBuildVersion = -1;
     m_isMacGdb = false;
-    m_isSynchronous = false;
+    m_hasPython = false;
     m_registerNamesListed = false;
 
     m_fullToShortName.clear();
@@ -698,8 +683,8 @@ void GdbEngine::maybeHandleInferiorPidChanged(const QString &pid0)
     debugMessage(_("FOUND PID %1").arg(pid));    
 
     handleInferiorPidChanged(pid);
-    if (m_dumperInjectionLoad)
-        tryLoadDebuggingHelpers();
+    if (m_dumperInjectionLoad && !hasPython())
+        tryLoadDebuggingHelpersClassic();
 }
 
 void GdbEngine::postCommand(const QByteArray &command, AdapterCallback callback,
@@ -1023,17 +1008,10 @@ void GdbEngine::executeDebuggerCommand(const QString &command)
 // Called from CoreAdapter and AttachAdapter
 void GdbEngine::updateAll()
 {
-    PENDING_DEBUG("UPDATING ALL\n");
-    QTC_ASSERT(state() == InferiorUnrunnable || state() == InferiorStopped, /**/);
-    tryLoadDebuggingHelpers();
-    reloadModulesInternal();
-    postCommand("-stack-list-frames", WatchUpdate, CB(handleStackListFrames),
-        QVariant::fromValue<StackCookie>(StackCookie(false, true)));
-    manager()->stackHandler()->setCurrentIndex(0);
-    if (supportsThreads())
-        postCommand("-thread-list-ids", WatchUpdate, CB(handleStackListThreads), 0);
-    manager()->reloadRegisters();
-    updateLocals(); 
+    if (hasPython())
+        updateAllPython();
+    else
+        updateAllClassic();
 }
 
 void GdbEngine::handleQuerySources(const GdbResponse &response)
@@ -1324,7 +1302,7 @@ void GdbEngine::handleStopResponse(const GdbMi &data)
     if (isSynchroneous())
         initHelpers = false;
     if (initHelpers) {
-        tryLoadDebuggingHelpers();
+        tryLoadDebuggingHelpersClassic();
         QVariant var = QVariant::fromValue<GdbMi>(data);
         postCommand("p 4", CB(handleStop1), var);  // dummy
     } else {
@@ -1483,13 +1461,13 @@ void GdbEngine::handleShowVersion(const GdbResponse &response)
     }
 }
 
-void GdbEngine::handleIsSynchroneous(const GdbResponse &response)
+void GdbEngine::handleHasPython(const GdbResponse &response)
 {
     Q_UNUSED(response);
     if (response.resultClass == GdbResultDone) {
-        m_isSynchronous = true;
+        m_hasPython = true;
     } else {
-        m_isSynchronous = false;
+        m_hasPython = false;
     }
 }
 
@@ -1867,19 +1845,6 @@ void GdbEngine::setTokenBarrier()
     m_oldestAcceptableToken = currentToken();
 }
 
-void GdbEngine::setDebugDebuggingHelpers(const QVariant &on)
-{
-    if (on.toBool()) {
-        debugMessage(_("SWITCHING ON DUMPER DEBUGGING"));
-        postCommand("set unwindonsignal off");
-        m_manager->breakByFunction(_("qDumpObjectData440"));
-        //updateLocals();
-    } else {
-        debugMessage(_("SWITCHING OFF DUMPER DEBUGGING"));
-        postCommand("set unwindonsignal on");
-    }
-}
-
 
 //////////////////////////////////////////////////////////////////////
 //
@@ -2754,8 +2719,8 @@ bool GdbEngine::supportsThreads() const
 //
 //////////////////////////////////////////////////////////////////////
 
-static QString m_toolTipExpression;
-static QPoint m_toolTipPos;
+QString GdbEngine::m_toolTipExpression;
+QPoint GdbEngine::m_toolTipPos;
 
 bool GdbEngine::showToolTip()
 {
@@ -2934,14 +2899,6 @@ static void setWatchDataSAddress(WatchData &data, const GdbMi &mi)
         data.saddr = mi.data();
 }
 
-void GdbEngine::setUseDebuggingHelpers(const QVariant &on)
-{
-    //qDebug() << "SWITCHING ON/OFF DUMPER DEBUGGING:" << on;
-    Q_UNUSED(on)
-    setTokenBarrier();
-    updateLocals();
-}
-
 void GdbEngine::setAutoDerefPointers(const QVariant &on)
 {
     Q_UNUSED(on)
@@ -2971,259 +2928,6 @@ bool GdbEngine::hasDebuggingHelperForType(const QString &type) const
     return m_dumperHelper.type(type) != QtDumperHelper::UnknownType;
 }
 
-static inline QString msgRetrievingWatchData(int pending)
-{
-    return GdbEngine::tr("Retrieving data for watch view (%n requests pending)...", 0, pending);
-}
-
-void GdbEngine::runDirectDebuggingHelper(const WatchData &data, bool dumpChildren)
-{
-    Q_UNUSED(dumpChildren)
-    QByteArray type = data.type.toLatin1();
-    QByteArray 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);
-    postCommand(cmd, WatchUpdate, CB(handleDebuggingHelperValue3), var);
-
-    showStatusMessage(msgRetrievingWatchData(m_pendingRequests + 1), 10000);
-}
-
-void GdbEngine::runDebuggingHelper(const WatchData &data0, bool dumpChildren)
-{
-    if (m_debuggingHelperState != DebuggingHelperAvailable) {
-        runDirectDebuggingHelper(data0, dumpChildren);
-        return;
-    }
-    WatchData data = data0;
-
-    // Avoid endless loops created by faulty dumpers.
-    QByteArray processedName = QByteArray::number(dumpChildren) + '-' + data.iname;
-    if (m_processedNames.contains(processedName)) {
-        gdbInputAvailable(LogStatus,
-            _("<Breaking endless loop for " + data.iname + ">"));
-        data.setAllUnneeded();
-        data.setValue(_("<unavailable>"));
-        data.setHasChildren(false);
-        insertData(data);
-        return; 
-    }
-    m_processedNames.insert(processedName);
-
-    QByteArray params;
-    QStringList extraArgs;
-    const QtDumperHelper::TypeData td = m_dumperHelper.typeData(data0.type);
-    m_dumperHelper.evaluationParameters(data, td, QtDumperHelper::GdbDebugger, &params, &extraArgs);
-
-    //int protocol = (data.iname.startsWith("watch") && data.type == "QImage") ? 3 : 2;
-    //int protocol = data.iname.startsWith("watch") ? 3 : 2;
-    const int protocol = 2;
-    //int protocol = isDisplayedIName(data.iname) ? 3 : 2;
-
-    QByteArray addr;
-    if (data.addr.startsWith("0x"))
-        addr = "(void*)" + data.addr;
-    else if (data.exp.isEmpty()) // happens e.g. for QAbstractItem
-        addr = "0";
-    else
-        addr = "&(" + data.exp + ')';
-
-    sendWatchParameters(params);
-
-    QString cmd;
-    QTextStream(&cmd) << "call " << "(void*)qDumpObjectData440(" <<
-            protocol << ",0," <<  addr << ',' << (dumpChildren ? "1" : "0")
-            << ',' << extraArgs.join(QString(_c(','))) <<  ')';
-
-    postCommand(cmd.toLatin1(), WatchUpdate | NonCriticalResponse);
-
-    showStatusMessage(msgRetrievingWatchData(m_pendingRequests + 1), 10000);
-
-    // retrieve response
-    postCommand("p (char*)&qDumpOutBuffer", WatchUpdate,
-        CB(handleDebuggingHelperValue2), qVariantFromValue(data));
-}
-
-void GdbEngine::createGdbVariable(const WatchData &data)
-{
-    if (data.iname == "local.flist.0") {
-        int i = 1;
-        Q_UNUSED(i);
-    }
-    postCommand("-var-delete \"" + data.iname + '"', WatchUpdate);
-    QByteArray exp = data.exp;
-    if (exp.isEmpty() && data.addr.startsWith("0x"))
-        exp = "*(" + gdbQuoteTypes(data.type).toLatin1() + "*)" + data.addr;
-    QVariant val = QVariant::fromValue<WatchData>(data);
-    postCommand("-var-create \"" + data.iname + "\" * \"" + exp + '"',
-        WatchUpdate, CB(handleVarCreate), val);
-}
-
-void GdbEngine::updateSubItem(const WatchData &data0)
-{
-    WatchData data = data0;
-    #if DEBUG_SUBITEM
-    qDebug() << "UPDATE SUBITEM:" << data.toString();
-    #endif
-    QTC_ASSERT(data.isValid(), return);
-
-    // in any case we need the type first
-    if (data.isTypeNeeded()) {
-        // This should only happen if we don't have a variable yet.
-        // Let's play safe, though.
-        if (!data.variable.isEmpty()) {
-            // Update: It does so for out-of-scope watchers.
-            #if 1
-            qDebug() << "FIXME: GdbEngine::updateSubItem:"
-                 << data.toString() << "should not happen";
-            #else
-            data.setType(WatchData::msgNotInScope());
-            data.setValue(WatchData::msgNotInScope());
-            data.setHasChildren(false);
-            insertData(data);
-            return;
-            #endif
-        }
-        // The WatchVarCreate handler will receive type information
-        // and re-insert a WatchData item with correct type, so
-        // we will not re-enter this bit.
-        // FIXME: Concurrency issues?
-        createGdbVariable(data);
-        return;
-    }
-
-    // we should have a type now. this is relied upon further below
-    QTC_ASSERT(!data.type.isEmpty(), return);
-
-    // a common case that can be easily solved
-    if (data.isChildrenNeeded() && isPointerType(data.type)
-        && !hasDebuggingHelperForType(data.type)) {
-        // We sometimes know what kind of children pointers have
-        #if DEBUG_SUBITEM
-        qDebug() << "IT'S A POINTER";
-        #endif
-    
-        if (theDebuggerBoolSetting(AutoDerefPointers)) {
-            // Try automatic dereferentiation
-            data.exp = "(*(" + data.exp + "))";
-            data.type = data.type + _("."); // FIXME: fragile HACK to avoid recursion
-            insertData(data);
-        } else {
-            data.setChildrenUnneeded();
-            insertData(data);
-            WatchData data1;
-            data1.iname = data.iname + ".*";
-            data1.name = QLatin1Char('*') + data.name;
-            data1.exp = "(*(" + data.exp + "))";
-            data1.type = stripPointerType(data.type);
-            data1.setValueNeeded();
-            data1.setChildrenUnneeded();
-            insertData(data1);
-        }
-        return;
-    }
-
-    if (data.isValueNeeded() && hasDebuggingHelperForType(data.type)) {
-        #if DEBUG_SUBITEM
-        qDebug() << "UPDATE SUBITEM: CUSTOMVALUE";
-        #endif
-        runDebuggingHelper(data, manager()->watchHandler()->isExpandedIName(data.iname));
-        return;
-    }
-
-/*
-    if (data.isValueNeeded() && data.exp.isEmpty()) {
-        #if DEBUG_SUBITEM
-        qDebug() << "UPDATE SUBITEM: NO EXPRESSION?";
-        #endif
-        data.setError("<no expression given>");
-        insertData(data);
-        return;
-    }
-*/
-
-    if (data.isValueNeeded() && data.variable.isEmpty()) {
-        #if DEBUG_SUBITEM
-        qDebug() << "UPDATE SUBITEM: VARIABLE NEEDED FOR VALUE";
-        #endif
-        createGdbVariable(data);
-        // the WatchVarCreate handler will re-insert a WatchData
-        // item, with valueNeeded() set.
-        return;
-    }
-
-    if (data.isValueNeeded()) {
-        QTC_ASSERT(!data.variable.isEmpty(), return); // tested above
-        #if DEBUG_SUBITEM
-        qDebug() << "UPDATE SUBITEM: VALUE";
-        #endif
-        QByteArray cmd = "-var-evaluate-expression \"" + data.iname + '"';
-        postCommand(cmd, WatchUpdate, CB(handleEvaluateExpression),
-            QVariant::fromValue(data));
-        return;
-    }
-
-    if (data.isChildrenNeeded() && hasDebuggingHelperForType(data.type)) {
-        #if DEBUG_SUBITEM
-        qDebug() << "UPDATE SUBITEM: CUSTOMVALUE WITH CHILDREN";
-        #endif
-        runDebuggingHelper(data, true);
-        return;
-    }
-
-    if (data.isChildrenNeeded() && data.variable.isEmpty()) {
-        #if DEBUG_SUBITEM
-        qDebug() << "UPDATE SUBITEM: VARIABLE NEEDED FOR CHILDREN";
-        #endif
-        createGdbVariable(data);
-        // the WatchVarCreate handler will re-insert a WatchData
-        // item, with childrenNeeded() set.
-        return;
-    }
-
-    if (data.isChildrenNeeded()) {
-        QTC_ASSERT(!data.variable.isEmpty(), return); // tested above
-        QByteArray cmd = "-var-list-children --all-values \"" + data.variable + '"';
-        postCommand(cmd, WatchUpdate, CB(handleVarListChildren), QVariant::fromValue(data));
-        return;
-    }
-
-    if (data.isHasChildrenNeeded() && hasDebuggingHelperForType(data.type)) {
-        #if DEBUG_SUBITEM
-        qDebug() << "UPDATE SUBITEM: CUSTOMVALUE WITH CHILDREN";
-        #endif
-        runDebuggingHelper(data, manager()->watchHandler()->isExpandedIName(data.iname));
-        return;
-    }
-
-//#if !X
-    if (data.isHasChildrenNeeded() && data.variable.isEmpty()) {
-        #if DEBUG_SUBITEM
-        qDebug() << "UPDATE SUBITEM: VARIABLE NEEDED FOR CHILDCOUNT";
-        #endif
-        createGdbVariable(data);
-        // the WatchVarCreate handler will re-insert a WatchData
-        // item, with childrenNeeded() set.
-        return;
-    }
-//#endif
-
-    if (data.isHasChildrenNeeded()) {
-        QTC_ASSERT(!data.variable.isEmpty(), return); // tested above
-        QByteArray cmd = "-var-list-children --all-values \"" + data.variable + '"';
-        postCommand(cmd, Discardable,
-            CB(handleVarListChildren), QVariant::fromValue(data));
-        return;
-    }
-
-    qDebug() << "FIXME: UPDATE SUBITEM:" << data.toString();
-    QTC_ASSERT(false, return);
-}
 
 void GdbEngine::updateWatchData(const WatchData &data)
 {
@@ -3281,7 +2985,7 @@ void GdbEngine::updateWatchDataHelper(const WatchData &data)
     //qDebug() << data.toString();
     #endif
 
-    updateSubItem(data);
+    updateSubItemClassic(data);
     //PENDING_DEBUG("INTERNAL TRIGGERING UPDATE WATCH MODEL");
     --m_pendingRequests;
     PENDING_DEBUG("UPDATE WATCH DONE BUMPS PENDING DOWN TO " << m_pendingRequests);
@@ -3302,51 +3006,7 @@ void GdbEngine::rebuildModel()
     showToolTip();
 }
 
-static inline double getDumperVersion(const GdbMi &contents)
-{
-    const GdbMi dumperVersionG = contents.findChild("dumperversion");
-    if (dumperVersionG.type() != GdbMi::Invalid) {
-        bool ok;
-        const double v = QString::fromAscii(dumperVersionG.data()).toDouble(&ok);
-        if (ok)
-            return v;
-    }
-    return 1.0;
-}
-
-void GdbEngine::handleQueryDebuggingHelper(const GdbResponse &response)
-{
-    const double dumperVersionRequired = 1.0;
-    //qDebug() << "DATA DUMPER TRIAL:" << response.toString();
-
-    GdbMi contents;
-    QTC_ASSERT(parseConsoleStream(response, &contents), qDebug() << response.toString());
-    const bool ok = m_dumperHelper.parseQuery(contents, QtDumperHelper::GdbDebugger)
-        && m_dumperHelper.typeCount();
-    if (ok) {
-        // Get version and sizes from dumpers. Expression cache
-        // currently causes errors.
-        const double dumperVersion = getDumperVersion(contents);
-        if (dumperVersion < dumperVersionRequired) {
-            manager()->showQtDumperLibraryWarning(
-                QtDumperHelper::msgDumperOutdated(dumperVersionRequired, dumperVersion));
-            m_debuggingHelperState = DebuggingHelperUnavailable;
-            return;
-        }
-        m_debuggingHelperState = DebuggingHelperAvailable;
-        const QString successMsg = tr("Dumper version %1, %n custom dumpers found.",
-            0, m_dumperHelper.typeCount()).arg(dumperVersion);
-        showStatusMessage(successMsg);
-    } else {
-        if (!m_dumperInjectionLoad) // Retry if thread has not terminated yet.
-            m_debuggingHelperState = DebuggingHelperUnavailable;
-        showStatusMessage(tr("Debugging helpers not found."));
-    }
-    //qDebug() << m_dumperHelper.toString(true);
-    //qDebug() << m_availableSimpleDebuggingHelpers << "DATA DUMPERS AVAILABLE";
-}
-
-static inline QByteArray arrayFillCommand(const char *array, const QByteArray &params)
+static QByteArray arrayFillCommand(const char *array, const QByteArray &params)
 {
     char buf[50];
     sprintf(buf, "set {char[%d]} &%s = {", params.size(), array);
@@ -3465,45 +3125,6 @@ void GdbEngine::handleDebuggingHelperSetup(const GdbResponse &response)
     }
 }
 
-void GdbEngine::handleDebuggingHelperValue2(const GdbResponse &response)
-{
-    WatchData data = response.cookie.value<WatchData>();
-    QTC_ASSERT(data.isValid(), return);
-
-    // The real dumper might have aborted without giving any answers.
-    // Remove traces of the question, too.
-    if (m_cookieForToken.contains(response.token - 1)) {
-        m_cookieForToken.remove(response.token - 1);
-        debugMessage(_("DETECTING LOST COMMAND %1").arg(response.token - 1));
-        --m_pendingRequests;
-        data.setError(WatchData::msgNotInScope());
-        insertData(data);
-        return;
-    }
-
-    //qDebug() << "CUSTOM VALUE RESULT:" << response.toString();
-    //qDebug() << "FOR DATA:" << data.toString() << response.resultClass;
-    if (response.resultClass != GdbResultDone) {
-        qDebug() << "STRANGE CUSTOM DUMPER RESULT DATA:" << data.toString();
-        return;
-    }
-
-    GdbMi contents;
-    if (!parseConsoleStream(response, &contents)) {
-        data.setError(WatchData::msgNotInScope());
-        insertData(data);
-        return;
-    }
-
-    setWatchDataType(data, response.data.findChild("type"));
-    setWatchDataDisplayedType(data, response.data.findChild("displaytype"));
-    QList<WatchData> list;
-    handleChildren(data, contents, &list);
-    //for (int i = 0; i != list.size(); ++i)
-    //    qDebug() << "READ: " << list.at(i).toString();
-    manager()->watchHandler()->insertBulkData(list);
-}
-
 void GdbEngine::handleChildren(const WatchData &data0, const GdbMi &item,
     QList<WatchData> *list)
 {
@@ -3575,280 +3196,15 @@ void GdbEngine::handleChildren(const WatchData &data0, const GdbMi &item,
     }
 }
 
-void GdbEngine::handleDebuggingHelperValue3(const GdbResponse &response)
-{
-    if (response.resultClass == GdbResultDone) {
-        WatchData data = response.cookie.value<WatchData>();
-        QByteArray out = response.data.findChild("consolestreamoutput").data();
-        while (out.endsWith(' ') || out.endsWith('\n'))
-            out.chop(1);
-        QList<QByteArray> list = out.split(' ');
-        //qDebug() << "RECEIVED" << response.toString() << "FOR" << data0.toString()
-        //    <<  " STREAM:" << out;
-        if (list.isEmpty()) {
-            //: Value for variable
-            data.setError(WatchData::msgNotInScope());
-            data.setAllUnneeded();
-            insertData(data);
-        } else if (data.type == __("QString")
-                || data.type.endsWith(__("::QString"))) {
-            QList<QByteArray> list = out.split(' ');
-            QString str;
-            int l = out.isEmpty() ? 0 : list.size();
-            for (int i = 0; i < l; ++i)
-                 str.append(list.at(i).toInt());
-            data.setValue(_c('"') + str + _c('"'));
-            data.setHasChildren(false);
-            data.setAllUnneeded();
-            insertData(data);
-        } else if (data.type == __("QStringList")
-                || data.type.endsWith(__("::QStringList"))) {
-            if (out.isEmpty()) {
-                data.setValue(tr("<0 items>"));
-                data.setHasChildren(false);
-                data.setAllUnneeded();
-                insertData(data);
-            } else {
-                int l = list.size();
-                //: In string list
-                data.setValue(tr("<%n items>", 0, l));
-                data.setHasChildren(!list.empty());
-                data.setAllUnneeded();
-                insertData(data);
-                for (int i = 0; i < l; ++i) {
-                    WatchData data1;
-                    data1.name = _("[%1]").arg(i);
-                    data1.type = data.type.left(data.type.size() - 4);
-                    data1.iname = data.iname + '.' + QByteArray::number(i);
-                    data1.addr = list.at(i);
-                    data1.exp = "((" + gdbQuoteTypes(data1.type).toLatin1() + "*)" + data1.addr + ")";
-                    data1.setHasChildren(false);
-                    data1.setValueNeeded();
-                    QByteArray cmd = "qdumpqstring (" + data1.exp + ')';
-                    QVariant var;
-                    var.setValue(data1);
-                    postCommand(cmd, WatchUpdate, CB(handleDebuggingHelperValue3), var);
-                }
-            }
-        } else {
-            //: Value for variable
-            data.setError(WatchData::msgNotInScope());
-            data.setAllUnneeded();
-            insertData(data);
-        }
-    } else {
-        WatchData data = response.cookie.value<WatchData>();
-        data.setError(WatchData::msgNotInScope());
-        data.setAllUnneeded();
-        insertData(data);
-    }
-}
-
 void GdbEngine::updateLocals(const QVariant &cookie)
 {
     m_pendingRequests = 0;
-    if (isSynchroneous()) {
-        if (m_gdbAdapter->isTrkAdapter()) {
-            postCommand("-stack-list-locals 0",
-                WatchUpdate, CB(handleStackListLocals0));
-        } else {
-            updateLocalsSync(QByteArray());
-        }
-    } else {
-        m_processedNames.clear();
-
-        PENDING_DEBUG("\nRESET PENDING");
-        //m_toolTipCache.clear();
-        m_toolTipExpression.clear();
-        manager()->watchHandler()->beginCycle();
-
-        // Asynchronous load of injected library, initialize in first stop
-        if (m_dumperInjectionLoad && m_debuggingHelperState == DebuggingHelperLoadTried
-                && m_dumperHelper.typeCount() == 0
-                && inferiorPid() > 0)
-            tryQueryDebuggingHelpers();
-
-        QByteArray level = QByteArray::number(currentFrame());
-        // '2' is 'list with type and value'
-        QByteArray cmd = "-stack-list-arguments 2 " + level + ' ' + level;
-        postCommand(cmd, WatchUpdate, CB(handleStackListArguments));
-        // '2' is 'list with type and value'
-        postCommand("-stack-list-locals 2", WatchUpdate,
-            CB(handleStackListLocals), cookie); // stage 2/2
-    }
+    if (hasPython())
+        updateLocalsPython(QByteArray());
+    else 
+        updateLocalsClassic(cookie);
 }
 
-void GdbEngine::handleStackListLocals0(const GdbResponse &response)
-{
-    if (response.resultClass == GdbResultDone) {
-        // 44^done,data={locals=[name="model",name="backString",...]}
-        QByteArray varList = "vars"; // Dummy entry, will be stripped by dumper.
-        foreach (const GdbMi &child, response.data.findChild("locals").children()) {
-            varList.append(',');
-            varList.append(child.data());
-        }
-        updateLocalsSync(varList);
-    }
-}
-
-void GdbEngine::updateLocalsSync(const QByteArray &varList)
-{
-    m_processedNames.clear();
-    manager()->watchHandler()->beginCycle();
-    //m_toolTipExpression.clear();
-    WatchHandler *handler = m_manager->watchHandler();
-
-    QByteArray expanded;
-    QSet<QByteArray> expandedINames = handler->expandedINames();
-    QSetIterator<QByteArray> jt(expandedINames);
-    while (jt.hasNext()) {
-        expanded.append(jt.next());
-        expanded.append(',');
-    }
-    if (expanded.isEmpty())
-        expanded.append("defaults,");
-    expanded.chop(1);
-
-    QByteArray watchers;
-    if (!m_toolTipExpression.isEmpty())
-        watchers += m_toolTipExpression.toLatin1()
-            + "#" + tooltipINameForExpression(m_toolTipExpression.toLatin1());
-
-    QHash<QByteArray, int> watcherNames = handler->watcherNames();
-    QHashIterator<QByteArray, int> it(watcherNames);
-    while (it.hasNext()) {
-        it.next();
-        if (!watchers.isEmpty())
-            watchers += "##";
-        if (it.key() == WatchHandler::watcherEditPlaceHolder().toLatin1())
-            watchers += "<Edit>#watch." + QByteArray::number(it.value());
-        else
-            watchers += it.key() + "#watch." + QByteArray::number(it.value());
-    }
-
-    QByteArray options;
-    if (theDebuggerBoolSetting(UseDebuggingHelpers))
-        options += "fancy,";
-    if (theDebuggerBoolSetting(AutoDerefPointers))
-        options += "autoderef,";
-    if (options.isEmpty())
-        options += "defaults,";
-    options.chop(1);
-
-    postCommand("bb " + options + " @" + varList + ' '
-            + expanded + ' ' + watchers.toHex(),
-        WatchUpdate, CB(handleStackFrame));
-}
-
-
-void GdbEngine::handleStackFrame(const GdbResponse &response)
-{
-    if (response.resultClass == GdbResultDone) {
-        QByteArray out = response.data.findChild("consolestreamoutput").data();
-        while (out.endsWith(' ') || out.endsWith('\n'))
-            out.chop(1);
-        //qDebug() << "SECOND CHUNK: " << out;
-        int pos = out.indexOf("data=");
-        if (pos != 0) {
-            qDebug() << "DISCARDING JUNK AT BEGIN OF RESPONSE: "
-                << out.left(pos);
-            out = out.mid(pos);
-        }
-        GdbMi all;
-        all.fromStringMultiple(out);
-        //qDebug() << "ALL: " << all.toString();
-        
-        GdbMi data = all.findChild("data");
-        QList<WatchData> list;
-        foreach (const GdbMi &child, data.children()) {
-            WatchData dummy;
-            dummy.iname = child.findChild("iname").data();
-            dummy.name = _(child.findChild("name").data());
-            //qDebug() << "CHILD: " << child.toString();
-            handleChildren(dummy, child, &list);
-        }
-        manager()->watchHandler()->insertBulkData(list);
-        //for (int i = 0; i != list.size(); ++i)
-        //    qDebug() << "LOCAL: " << list.at(i).toString();
-
-        PENDING_DEBUG("AFTER handleStackFrame()");
-        // FIXME: This should only be used when updateLocals() was
-        // triggered by expanding an item in the view.
-        if (m_pendingRequests <= 0) {
-            PENDING_DEBUG("\n\n ....  AND TRIGGERS MODEL UPDATE\n");
-            rebuildModel();
-        }
-    } else {
-        debugMessage(_("DUMPER FAILED: " + response.toString()));
-    }
-}
-
-void GdbEngine::handleStackListArguments(const GdbResponse &response)
-{
-    // stage 1/2
-
-    // Linux:
-    // 12^done,stack-args=
-    //   [frame={level="0",args=[
-    //     {name="argc",type="int",value="1"},
-    //     {name="argv",type="char **",value="(char **) 0x7..."}]}]
-    // Mac:
-    // 78^done,stack-args=
-    //    {frame={level="0",args={
-    //      varobj=
-    //        {exp="this",value="0x38a2fab0",name="var21",numchild="3",
-    //             type="CurrentDocumentFind *  const",typecode="PTR",
-    //             dynamic_type="",in_scope="true",block_start_addr="0x3938e946",
-    //             block_end_addr="0x3938eb2d"},
-    //      varobj=
-    //         {exp="before",value="@0xbfffb9f8: {d = 0x3a7f2a70}",
-    //              name="var22",numchild="1",type="const QString  ...} }}}
-    //
-    // In both cases, iterating over the children of stack-args/frame/args
-    // is ok.
-    m_currentFunctionArgs.clear();
-    if (response.resultClass == GdbResultDone) {
-        const GdbMi list = response.data.findChild("stack-args");
-        const GdbMi frame = list.findChild("frame");
-        const GdbMi args = frame.findChild("args");
-        m_currentFunctionArgs = args.children();
-    } else {
-        qDebug() << "FIXME: GdbEngine::handleStackListArguments: should not happen"
-            << response.toString();
-    }
-}
-
-void GdbEngine::handleStackListLocals(const GdbResponse &response)
-{
-    // stage 2/2
-
-    // There could be shadowed variables
-    QList<GdbMi> locals = response.data.findChild("locals").children();
-    locals += m_currentFunctionArgs;
-    QMap<QByteArray, int> seen;
-    // If desired, retrieve list of uninitialized variables looking at
-    // the current frame. This is invoked first time after a stop from
-    // handleStop1, which passes on the frame as cookie. The whole stack
-    // is not known at this point.
-    QStringList uninitializedVariables;
-    if (theDebuggerAction(UseCodeModel)->isChecked()) {
-        const StackFrame frame = qVariantCanConvert<Debugger::Internal::StackFrame>(response.cookie) ?
-                                 qVariantValue<Debugger::Internal::StackFrame>(response.cookie) :
-                                 m_manager->stackHandler()->currentFrame();
-        if (frame.isUsable())
-            getUninitializedVariables(m_manager->cppCodeModelSnapshot(),
-                                      frame.function, frame.file, frame.line,
-                                      &uninitializedVariables);
-    }
-    QList<WatchData> list;
-    foreach (const GdbMi &item, locals) {
-        const WatchData data = localVariable(item, uninitializedVariables, &seen);
-        if (data.isValid())
-            list.push_back(data);
-    }
-    manager()->watchHandler()->insertBulkData(list);
-    manager()->watchHandler()->updateWatchers();
-}
 
 // Parse a local variable from GdbMi
 WatchData GdbEngine::localVariable(const GdbMi &item,
@@ -4104,134 +3460,6 @@ QString GdbEngine::qtDumperLibraryName() const
     return m_manager->qtDumperLibraryName();
 }
 
-bool GdbEngine::checkDebuggingHelpers()
-{
-    if (!manager()->qtDumperLibraryEnabled())
-        return false;
-    const QString lib = qtDumperLibraryName();
-    //qDebug() << "DUMPERLIB:" << lib;
-    const QFileInfo fi(lib);
-    if (!fi.exists()) {
-        const QStringList &locations = manager()->qtDumperLibraryLocations();
-        const QString loc = locations.join(QLatin1String(", "));
-        const QString msg = tr("The debugging helper library was not found at %1.").arg(loc);
-        debugMessage(msg);
-        manager()->showQtDumperLibraryWarning(msg);
-        return false;
-    }
-    return true;
-}
-
-void GdbEngine::setDebuggingHelperState(DebuggingHelperState s)
-{
-    m_debuggingHelperState = s;
-}
-
-void GdbEngine::tryLoadDebuggingHelpers()
-{
-    if (isSynchroneous())
-        return;
-    switch (m_debuggingHelperState) {
-    case DebuggingHelperUninitialized:
-        break;
-    case DebuggingHelperLoadTried:
-        tryQueryDebuggingHelpers();
-        return;
-    case DebuggingHelperAvailable:
-    case DebuggingHelperUnavailable:
-        return;
-    }
-
-    if (m_gdbAdapter->dumperHandling() == AbstractGdbAdapter::DumperNotAvailable) {
-        // Load at least gdb macro based dumpers.
-        QFile file(_(":/gdb/gdbmacros.txt"));
-        file.open(QIODevice::ReadOnly);
-        QByteArray contents = file.readAll(); 
-        m_debuggingHelperState = DebuggingHelperLoadTried;
-        postCommand(contents);
-        return;
-    }
-    if (m_dumperInjectionLoad && inferiorPid() <= 0) // Need PID to inject
-        return;
-
-    PENDING_DEBUG("TRY LOAD CUSTOM DUMPERS");
-    m_debuggingHelperState = DebuggingHelperUnavailable;
-    if (!checkDebuggingHelpers())
-        return;
-
-    m_debuggingHelperState = DebuggingHelperLoadTried;
-    QByteArray dlopenLib;
-    if (startParameters().startMode == StartRemote)
-        dlopenLib = startParameters().remoteDumperLib.toLocal8Bit();
-    else
-        dlopenLib = manager()->qtDumperLibraryName().toLocal8Bit();
-#if defined(Q_OS_WIN)
-    if (m_dumperInjectionLoad) {
-        /// Launch asynchronous remote thread to load.
-        SharedLibraryInjector injector(inferiorPid());
-        QString errorMessage;
-        const QString dlopenLibString = _(dlopenLib);
-        if (injector.remoteInject(dlopenLibString, false, &errorMessage)) {
-            debugMessage(_("Dumper injection loading triggered (%1)...").
-                         arg(dlopenLibString));
-        } else {
-            debugMessage(_("Dumper loading (%1) failed: %2").
-                         arg(dlopenLibString, errorMessage));
-            debugMessage(errorMessage);
-            manager()->showQtDumperLibraryWarning(errorMessage);
-            m_debuggingHelperState = DebuggingHelperUnavailable;
-            return;
-        }
-    } else {
-        debugMessage(_("Loading dumpers via debugger call (%1)...").
-                     arg(_(dlopenLib)));
-        postCommand("sharedlibrary .*"); // for LoadLibraryA
-        //postCommand("handle SIGSEGV pass stop print");
-        //postCommand("set unwindonsignal off");
-        postCommand("call LoadLibraryA(\"" + GdbMi::escapeCString(dlopenLib) + "\")",
-                    CB(handleDebuggingHelperSetup));
-        postCommand("sharedlibrary " + dotEscape(dlopenLib));
-    }
-#elif defined(Q_OS_MAC)
-    //postCommand("sharedlibrary libc"); // for malloc
-    //postCommand("sharedlibrary libdl"); // for dlopen
-    postCommand("call (void)dlopen(\"" + GdbMi::escapeCString(dlopenLib)
-                + "\", " STRINGIFY(RTLD_NOW) ")",
-        CB(handleDebuggingHelperSetup));
-    //postCommand("sharedlibrary " + dotEscape(dlopenLib));
-#else
-    //postCommand("p dlopen");
-    postCommand("sharedlibrary libc"); // for malloc
-    postCommand("sharedlibrary libdl"); // for dlopen
-    postCommand("call (void*)dlopen(\"" + GdbMi::escapeCString(dlopenLib)
-                + "\", " STRINGIFY(RTLD_NOW) ")",
-        CB(handleDebuggingHelperSetup));
-    // some older systems like CentOS 4.6 prefer this:
-    postCommand("call (void*)__dlopen(\"" + GdbMi::escapeCString(dlopenLib)
-                + "\", " STRINGIFY(RTLD_NOW) ")",
-        CB(handleDebuggingHelperSetup));
-    postCommand("sharedlibrary " + dotEscape(dlopenLib));
-#endif
-    if (!m_dumperInjectionLoad)
-        tryQueryDebuggingHelpers();
-}
-
-void GdbEngine::tryQueryDebuggingHelpers()
-{
-    // retrieve list of dumpable classes
-    postCommand("call (void*)qDumpObjectData440(1,0,0,0,0,0,0,0)");
-    postCommand("p (char*)&qDumpOutBuffer", CB(handleQueryDebuggingHelper));
-}
-
-void GdbEngine::recheckDebuggingHelperAvailability()
-{
-    if (m_gdbAdapter->dumperHandling() != AbstractGdbAdapter::DumperNotAvailable) {
-        // retrieve list of dumpable classes
-        postCommand("call (void*)qDumpObjectData440(1,0,0,0,0,0,0,0)");
-        postCommand("p (char*)&qDumpOutBuffer", CB(handleQueryDebuggingHelper));
-    }
-}
-
 void GdbEngine::watchPoint(const QPoint &pnt)
 {
     //qDebug() << "WATCH " << pnt;
@@ -4530,7 +3758,7 @@ bool GdbEngine::startGdb(const QStringList &args, const QString &gdb, const QStr
         NonCriticalResponse);
 
     postCommand("-interpreter-exec console \"help bb\"",
-        CB(handleIsSynchroneous));
+        CB(handleHasPython));
     //postCommand("-enable-timings");
     postCommand("set print static-members off"); // Seemingly doesn't work.
     //postCommand("set debug infrun 1");
@@ -4611,7 +3839,7 @@ bool GdbEngine::startGdb(const QStringList &args, const QString &gdb, const QStr
         }
     }
     if (m_gdbAdapter->dumperHandling() == AbstractGdbAdapter::DumperLoadedByGdbPreload
-        && checkDebuggingHelpers()) {        
+        && checkDebuggingHelpers()) {
         QByteArray cmd = "set environment ";
         cmd += Debugger::Constants::Internal::LD_PRELOAD_ENV_VAR;
         cmd += ' ';
@@ -4622,6 +3850,11 @@ bool GdbEngine::startGdb(const QStringList &args, const QString &gdb, const QStr
     return true;
 }
 
+bool GdbEngine::checkDebuggingHelpers()
+{
+    return !hasPython() && checkDebuggingHelpersClassic();
+}
+
 void GdbEngine::handleGdbError(QProcess::ProcessError error)
 {
     debugMessage(_("HANDLE GDB ERROR"));
@@ -4758,9 +3991,17 @@ QMessageBox * GdbEngine::showMessageBox(int icon, const QString &title,
     return m_manager->showMessageBox(icon, title, text, buttons);
 }
 
-bool GdbEngine::isSynchroneous() const
+void GdbEngine::setUseDebuggingHelpers(const QVariant &on)
+{
+    //qDebug() << "SWITCHING ON/OFF DUMPER DEBUGGING:" << on;
+    Q_UNUSED(on)
+    setTokenBarrier();
+    updateLocals();
+}
+
+bool GdbEngine::hasPython() const
 {
-    return m_isSynchronous;
+    return m_hasPython;
 }
 
 //
diff --git a/src/plugins/debugger/gdb/gdbengine.h b/src/plugins/debugger/gdb/gdbengine.h
index 8123827b6345d527f586bf89faa828fce5997da2..da0be04d5c23c36120719530180fdb9c1a5bcb75 100644
--- a/src/plugins/debugger/gdb/gdbengine.h
+++ b/src/plugins/debugger/gdb/gdbengine.h
@@ -264,17 +264,17 @@ private: ////////// Gdb Output, State & Capability Handling //////////
     void handleStop1(const GdbMi &data);
     StackFrame parseStackFrame(const GdbMi &mi, int level);
 
-    virtual bool isSynchroneous() const;
+    virtual bool hasPython() const;
     bool supportsThreads() const;
 
     // Gdb initialization sequence
     void handleShowVersion(const GdbResponse &response);
-    void handleIsSynchroneous(const GdbResponse &response);
+    void handleHasPython(const GdbResponse &response);
 
     int m_gdbVersion; // 6.8.0 is 60800
     int m_gdbBuildVersion; // MAC only?
     bool m_isMacGdb;
-    bool m_isSynchronous; // Can act synchronously?
+    bool m_hasPython;
 
 private: ////////// Inferior Management //////////
 
@@ -393,10 +393,11 @@ private: ////////// View & Data Stuff //////////
     // Stack specific stuff
     //
     void updateAll();
+        void updateAllClassic();
+        void updateAllPython();
     void handleStackListFrames(const GdbResponse &response);
     void handleStackSelectThread(const GdbResponse &response);
     void handleStackListThreads(const GdbResponse &response);
-    void handleStackFrame(const GdbResponse &response);
     Q_SLOT void reloadStack(bool forceGotoLocation);
     Q_SLOT virtual void reloadFullStack();
     int currentFrame() const;
@@ -418,7 +419,7 @@ private: ////////// View & Data Stuff //////////
     void handleWatchPoint(const GdbResponse &response);
 
     // FIXME: BaseClass. called to improve situation for a watch item
-    void updateSubItem(const WatchData &data);
+    void updateSubItemClassic(const WatchData &data);
     void handleChildren(const WatchData &parent, const GdbMi &child,
         QList<WatchData> *insertions);
 
@@ -429,10 +430,10 @@ private: ////////// View & Data Stuff //////////
 
     void insertData(const WatchData &data);
     void sendWatchParameters(const QByteArray &params0);
-    void createGdbVariable(const WatchData &data);
+    void createGdbVariableClassic(const WatchData &data);
 
-    void runDebuggingHelper(const WatchData &data, bool dumpChildren);
-    void runDirectDebuggingHelper(const WatchData &data, bool dumpChildren);
+    void runDebuggingHelperClassic(const WatchData &data, bool dumpChildren);
+    void runDirectDebuggingHelperClassic(const WatchData &data, bool dumpChildren);
     bool hasDebuggingHelperForType(const QString &type) const;
 
     void handleVarListChildren(const GdbResponse &response);
@@ -442,20 +443,25 @@ private: ////////// View & Data Stuff //////////
     void handleVarAssign(const GdbResponse &response);
     void handleEvaluateExpression(const GdbResponse &response);
     //void handleToolTip(const GdbResponse &response);
-    void handleQueryDebuggingHelper(const GdbResponse &response);
-    void handleDebuggingHelperValue2(const GdbResponse &response);
-    void handleDebuggingHelperValue3(const GdbResponse &response);
+    void handleQueryDebuggingHelperClassic(const GdbResponse &response);
+    void handleDebuggingHelperValue2Classic(const GdbResponse &response);
+    void handleDebuggingHelperValue3Classic(const GdbResponse &response);
     void handleDebuggingHelperEditValue(const GdbResponse &response);
     void handleDebuggingHelperSetup(const GdbResponse &response);
 
     void updateLocals(const QVariant &cookie = QVariant());
-    void handleStackListLocals(const GdbResponse &response);
-    void handleStackListLocals0(const GdbResponse &response);
+        void updateLocalsClassic(const QVariant &cookie);
+        void updateLocalsPython(const QByteArray &varList);
+            void handleStackFramePython(const GdbResponse &response);
+        
+    void handleStackListLocalsClassic(const GdbResponse &response);
+    void handleStackListLocalsPython(const GdbResponse &response);
+
     WatchData localVariable(const GdbMi &item,
                             const QStringList &uninitializedVariables,
                             QMap<QByteArray, int> *seen);
     void setLocals(const QList<GdbMi> &locals);
-    void handleStackListArguments(const GdbResponse &response);
+    void handleStackListArgumentsClassic(const GdbResponse &response);
     void setWatchDataType(WatchData &data, const GdbMi &mi);
     void setWatchDataDisplayedType(WatchData &data, const GdbMi &mi);
 
@@ -465,13 +471,14 @@ private: ////////// View & Data Stuff //////////
 private: ////////// Dumper Management //////////
     QString qtDumperLibraryName() const;
     bool checkDebuggingHelpers();
-    void setDebuggingHelperState(DebuggingHelperState);
-    void tryLoadDebuggingHelpers();
-    void tryQueryDebuggingHelpers();
-    Q_SLOT void recheckDebuggingHelperAvailability();
+        bool checkDebuggingHelpersClassic();
+    void setDebuggingHelperStateClassic(DebuggingHelperState);
+    void tryLoadDebuggingHelpersClassic();
+    void tryQueryDebuggingHelpersClassic();
+    Q_SLOT void recheckDebuggingHelperAvailabilityClassic();
     void connectDebuggingHelperActions();
     void disconnectDebuggingHelperActions();
-    Q_SLOT void setDebugDebuggingHelpers(const QVariant &on);
+    Q_SLOT void setDebugDebuggingHelpersClassic(const QVariant &on);
     Q_SLOT void setUseDebuggingHelpers(const QVariant &on);
 
     const bool m_dumperInjectionLoad;
@@ -486,7 +493,9 @@ private: ////////// Convenience Functions //////////
     void debugMessage(const QString &msg);
     QMainWindow *mainWindow() const;
 
-    void updateLocalsSync(const QByteArray &varList);
+    static QString m_toolTipExpression;
+    static QPoint m_toolTipPos;
+    static QByteArray tooltipINameForExpression(const QByteArray &exp);
 };
 
 } // namespace Internal
diff --git a/src/plugins/debugger/gdb/pythongdbengine.cpp b/src/plugins/debugger/gdb/pythongdbengine.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..8f57cd430a95bc237fb384ee152d7656d71ed0f3
--- /dev/null
+++ b/src/plugins/debugger/gdb/pythongdbengine.cpp
@@ -0,0 +1,177 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** Commercial Usage
+**
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Nokia.
+**
+** GNU Lesser General Public License Usage
+**
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file.  Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at http://qt.nokia.com/contact.
+**
+**************************************************************************/
+
+#include "gdbengine.h"
+
+#include "abstractgdbadapter.h"
+#include "debuggeractions.h"
+#include "debuggerstringutils.h"
+
+#include "watchhandler.h"
+#include "stackhandler.h"
+
+#include <utils/qtcassert.h>
+
+#define PRECONDITION QTC_ASSERT(hasPython(), /**/)
+#define CB(callback) &GdbEngine::callback, STRINGIFY(callback)
+
+
+namespace Debugger {
+namespace Internal {
+
+void GdbEngine::updateLocalsPython(const QByteArray &varList)
+{
+    PRECONDITION;
+    if (m_gdbAdapter->isTrkAdapter()) {
+        postCommand("-stack-list-locals 0",
+            WatchUpdate, CB(handleStackListLocalsPython));
+        return;
+    }
+    m_processedNames.clear();
+    manager()->watchHandler()->beginCycle();
+    //m_toolTipExpression.clear();
+    WatchHandler *handler = m_manager->watchHandler();
+
+    QByteArray expanded;
+    QSet<QByteArray> expandedINames = handler->expandedINames();
+    QSetIterator<QByteArray> jt(expandedINames);
+    while (jt.hasNext()) {
+        expanded.append(jt.next());
+        expanded.append(',');
+    }
+    if (expanded.isEmpty())
+        expanded.append("defaults,");
+    expanded.chop(1);
+
+    QByteArray watchers;
+    if (!m_toolTipExpression.isEmpty())
+        watchers += m_toolTipExpression.toLatin1()
+            + "#" + tooltipINameForExpression(m_toolTipExpression.toLatin1());
+
+    QHash<QByteArray, int> watcherNames = handler->watcherNames();
+    QHashIterator<QByteArray, int> it(watcherNames);
+    while (it.hasNext()) {
+        it.next();
+        if (!watchers.isEmpty())
+            watchers += "##";
+        if (it.key() == WatchHandler::watcherEditPlaceHolder().toLatin1())
+            watchers += "<Edit>#watch." + QByteArray::number(it.value());
+        else
+            watchers += it.key() + "#watch." + QByteArray::number(it.value());
+    }
+
+    QByteArray options;
+    if (theDebuggerBoolSetting(UseDebuggingHelpers))
+        options += "fancy,";
+    if (theDebuggerBoolSetting(AutoDerefPointers))
+        options += "autoderef,";
+    if (options.isEmpty())
+        options += "defaults,";
+    options.chop(1);
+
+    postCommand("bb " + options + " @" + varList + ' '
+            + expanded + ' ' + watchers.toHex(),
+        WatchUpdate, CB(handleStackFramePython));
+}
+
+void GdbEngine::handleStackListLocalsPython(const GdbResponse &response)
+{
+    PRECONDITION;
+    if (response.resultClass == GdbResultDone) {
+        // 44^done,data={locals=[name="model",name="backString",...]}
+        QByteArray varList = "vars"; // Dummy entry, will be stripped by dumper.
+        foreach (const GdbMi &child, response.data.findChild("locals").children()) {
+            varList.append(',');
+            varList.append(child.data());
+        }
+        updateLocalsPython(varList);
+    }
+}
+
+void GdbEngine::handleStackFramePython(const GdbResponse &response)
+{
+    PRECONDITION;
+    if (response.resultClass == GdbResultDone) {
+        QByteArray out = response.data.findChild("consolestreamoutput").data();
+        while (out.endsWith(' ') || out.endsWith('\n'))
+            out.chop(1);
+        //qDebug() << "SECOND CHUNK: " << out;
+        int pos = out.indexOf("data=");
+        if (pos != 0) {
+            qDebug() << "DISCARDING JUNK AT BEGIN OF RESPONSE: "
+                << out.left(pos);
+            out = out.mid(pos);
+        }
+        GdbMi all;
+        all.fromStringMultiple(out);
+        //qDebug() << "ALL: " << all.toString();
+        
+        GdbMi data = all.findChild("data");
+        QList<WatchData> list;
+        foreach (const GdbMi &child, data.children()) {
+            WatchData dummy;
+            dummy.iname = child.findChild("iname").data();
+            dummy.name = _(child.findChild("name").data());
+            //qDebug() << "CHILD: " << child.toString();
+            handleChildren(dummy, child, &list);
+        }
+        manager()->watchHandler()->insertBulkData(list);
+        //for (int i = 0; i != list.size(); ++i)
+        //    qDebug() << "LOCAL: " << list.at(i).toString();
+
+        //PENDING_DEBUG("AFTER handleStackFrame()");
+        // FIXME: This should only be used when updateLocals() was
+        // triggered by expanding an item in the view.
+        if (m_pendingRequests <= 0) {
+            //PENDING_DEBUG("\n\n ....  AND TRIGGERS MODEL UPDATE\n");
+            rebuildModel();
+        }
+    } else {
+        debugMessage(_("DUMPER FAILED: " + response.toString()));
+    }
+}
+
+// Called from CoreAdapter and AttachAdapter
+void GdbEngine::updateAllPython()
+{
+    PRECONDITION;
+    //PENDING_DEBUG("UPDATING ALL\n");
+    QTC_ASSERT(state() == InferiorUnrunnable || state() == InferiorStopped, /**/);
+    reloadModulesInternal();
+    postCommand("-stack-list-frames", WatchUpdate, CB(handleStackListFrames),
+        QVariant::fromValue<StackCookie>(StackCookie(false, true)));
+    manager()->stackHandler()->setCurrentIndex(0);
+    if (supportsThreads())
+        postCommand("-thread-list-ids", WatchUpdate, CB(handleStackListThreads), 0);
+    manager()->reloadRegisters();
+    updateLocals(); 
+}
+
+} // namespace Internal
+} // namespace Debugger
diff --git a/src/plugins/debugger/gdb/termgdbadapter.cpp b/src/plugins/debugger/gdb/termgdbadapter.cpp
index 6b096b28301f12bd9f7abc7a5648ddf775cf360d..768c004c09ff59c1d92fa6f49671edf8b36a96ca 100644
--- a/src/plugins/debugger/gdb/termgdbadapter.cpp
+++ b/src/plugins/debugger/gdb/termgdbadapter.cpp
@@ -100,7 +100,7 @@ void TermGdbAdapter::startAdapter()
         var += QLatin1Char('=');
         var += m_engine->qtDumperLibraryName();
         environment.push_back(var);
-        m_engine->setDebuggingHelperState(DebuggingHelperLoadTried);
+        m_engine->setDebuggingHelperStateClassic(DebuggingHelperLoadTried);
     }
     m_stubProc.setEnvironment(environment);
     // FIXME: Starting the stub implies starting the inferior. This is