diff --git a/share/qtcreator/gdbmacros/gdbmacros.cpp b/share/qtcreator/gdbmacros/gdbmacros.cpp
index 6277c5477cda6ddea509e1bd34dfdd7c981f382f..fdcbfad0f83370de09f8e06b95410c8aaf47af70 100644
--- a/share/qtcreator/gdbmacros/gdbmacros.cpp
+++ b/share/qtcreator/gdbmacros/gdbmacros.cpp
@@ -94,10 +94,10 @@ int qtGhVersion = QT_VERSION;
   \c{qDumpObjectData440()}.
 
   In any case, dumper processesing should end up in 
-  \c{handleProtocolVersion2and3()} and needs an entry in the bis switch there.
+  \c{handleProtocolVersion2and3()} and needs an entry in the big switch there.
 
   Next step is to create a suitable \c{static void qDumpFoo(QDumper &d)}
-  function. At the bare minimum it should contain something like:
+  function. At the bare minimum it should contain something like this:
 
 
   \c{
@@ -127,7 +127,7 @@ int qtGhVersion = QT_VERSION;
   \endlist
 
   If the current item has children, it might be queried to produce information
-  about thes children. In this case the dumper should use something like
+  about these children. In this case the dumper should use something like this:
 
   \c{
     if (d.dumpChildren) {
@@ -221,16 +221,19 @@ Q_DECL_EXPORT char qDumpOutBuffer[100000];
 
 namespace {
 
+static QByteArray strPtrConst = "* const";
+
 static bool isPointerType(const QByteArray &type)
 {
-    return type.endsWith("*") || type.endsWith("* const");
+    return type.endsWith('*') || type.endsWith(strPtrConst);
 }
 
-static QByteArray stripPointerType(QByteArray type)
+static QByteArray stripPointerType(const QByteArray &_type)
 {
-    if (type.endsWith("*"))
+    QByteArray type = _type;
+    if (type.endsWith('*'))
         type.chop(1);
-    if (type.endsWith("* const"))
+    if (type.endsWith(strPtrConst))
         type.chop(7);
     if (type.endsWith(' '))
         type.chop(1);
@@ -279,7 +282,10 @@ static bool isEqual(const char *s, const char *t)
 
 static bool startsWith(const char *s, const char *t)
 {
-    return qstrncmp(s, t, qstrlen(t)) == 0;
+    while (char c = *t++)
+        if (c != *s++)
+            return false;
+    return true;
 }
 
 // Check memory for read access and provoke segfault if nothing else helps.
@@ -293,11 +299,18 @@ static bool startsWith(const char *s, const char *t)
 #    define qCheckPointer(d) do { if (d) qProvokeSegFaultHelper = *(char*)d; } while (0)
 #endif
 
+#ifdef QT_NAMESPACE
 const char *stripNamespace(const char *type)
 {
-    static const size_t nslen = qstrlen(NS);
+    static const size_t nslen = strlen(NS);
     return startsWith(type, NS) ? type + nslen : type;
 }
+#else
+inline const char *stripNamespace(const char *type)
+{
+    return type;
+}
+#endif
 
 static bool isSimpleType(const char *type)
 {
@@ -1168,7 +1181,7 @@ static void qDumpQHashNode(QDumper &d)
 
     P(d, "numchild", 2);
     if (d.dumpChildren) {
-        // there is a hash specialization in cast the key are integers or shorts
+        // there is a hash specialization in case the keys are integers or shorts
         d << ",children=[";
         d.beginHash();
             P(d, "name", "key");
@@ -2679,7 +2692,7 @@ void *qDumpObjectData440(
 
         // This is a list of all available dumpers. Note that some templates
         // currently require special hardcoded handling in the debugger plugin.
-        // They are mentioned here nevertheless. For types that not listed
+        // They are mentioned here nevertheless. For types that are not listed
         // here, dumpers won't be used.
         d << "dumpers=["
             "\""NS"QByteArray\","
diff --git a/src/plugins/debugger/cdb/cdbdumperhelper.cpp b/src/plugins/debugger/cdb/cdbdumperhelper.cpp
index 541aa7ea1d0615303b4e67a295364b60ac74a89c..b76398254d0bb1d6c270da66a589416dae79fabf 100644
--- a/src/plugins/debugger/cdb/cdbdumperhelper.cpp
+++ b/src/plugins/debugger/cdb/cdbdumperhelper.cpp
@@ -571,7 +571,7 @@ CdbDumperHelper::DumpResult CdbDumperHelper::dumpType(const WatchData &wd, bool
     if (der == DumpExecuteSizeFailed)
         m_failedTypes.push_back(wd.type);    
     // log error
-    *errorMessage = *errorMessage = msgDumpFailed(wd, errorMessage);
+    *errorMessage = msgDumpFailed(wd, errorMessage);
     m_access->showDebuggerOutput(m_messagePrefix, *errorMessage);
     return DumpError;
 }
diff --git a/src/plugins/debugger/gdbengine.cpp b/src/plugins/debugger/gdbengine.cpp
index 653a6817b62afeb6e8c7f00cdbfd0aaff141efdc..12e1aa1623be3c9755b23ad3df52e763914e5d20 100644
--- a/src/plugins/debugger/gdbengine.cpp
+++ b/src/plugins/debugger/gdbengine.cpp
@@ -1824,9 +1824,9 @@ void GdbEngine::sendInsertBreakpoint(int index)
         //if (where.isEmpty())
         //    where = data->fileName;
 #endif
-        // we need something like   "\"file name.cpp\":100"  to
-        // survive the gdb command line parser with file names intact
-        where = _("\"\\\"") + where + _("\\\":") + data->lineNumber + _c('"');
+        // The argument is simply a C-quoted version of the argument to the
+        // non-MI "break" command, including the "original" quoting it wants.
+        where = _("\"\\\"") + GdbMi::escapeCString(where) + _("\\\":") + data->lineNumber + _c('"');
     } else {
         where = data->funcName;
     }
@@ -1987,6 +1987,8 @@ void GdbEngine::handleBreakInsert(const GdbResultRecord &record, const QVariant
         handler->updateMarkers();
     } else if (record.resultClass == GdbResultError) {
         const BreakpointData *data = handler->at(index);
+        // Note that it is perfectly correct that the file name is put
+        // in quotes but not escaped. GDB simply is like that.
 #ifdef Q_OS_LINUX
         //QString where = "\"\\\"" + data->fileName + "\\\":"
         //    + data->lineNumber + "\"";
@@ -3098,8 +3100,7 @@ void GdbEngine::handleQueryDebuggingHelper(const GdbResultRecord &record, const
     QByteArray out = output.data();
     out = out.mid(out.indexOf('"') + 2); // + 1 is success marker
     out = out.left(out.lastIndexOf('"'));
-    //out.replace('\'', '"');
-    out.replace("\\", "");
+    out.replace('\\', ""); // optimization: dumper output never needs real C unquoting
     out = "dummy={" + out + "}";
     //qDebug() << "OUTPUT: " << out;
 
@@ -3302,7 +3303,7 @@ void GdbEngine::handleDebuggingHelperValue2(const GdbResultRecord &record,
     QByteArray out = output.data();
 
     int markerPos = out.indexOf('"') + 1; // position of 'success marker'
-    if (markerPos == -1 || out.at(markerPos) == 'f') {  // 't' or 'f'
+    if (markerPos == 0 || out.at(markerPos) == 'f') {  // 't' or 'f'
         // custom dumper produced no output
         data.setError(strNotInScope);
         insertData(data);
@@ -3311,7 +3312,7 @@ void GdbEngine::handleDebuggingHelperValue2(const GdbResultRecord &record,
 
     out = out.mid(markerPos +  1);
     out = out.left(out.lastIndexOf('"'));
-    out.replace("\\", "");
+    out.replace('\\', ""); // optimization: dumper output never needs real C unquoting
     out = "dummy={" + out + "}";
 
     GdbMi contents;
@@ -3848,13 +3849,13 @@ void GdbEngine::tryLoadDebuggingHelpers()
     execCommand(_("sharedlibrary .*")); // for LoadLibraryA
     //execCommand(_("handle SIGSEGV pass stop print"));
     //execCommand(_("set unwindonsignal off"));
-    execCommand(_("call LoadLibraryA(\"") + lib + _("\")"),
+    execCommand(_("call LoadLibraryA(\"") + GdbMi::escapeCString(lib) + _("\")"),
         CB(handleDebuggingHelperSetup));
     execCommand(_("sharedlibrary ") + dotEscape(lib));
 #elif defined(Q_OS_MAC)
     //execCommand(_("sharedlibrary libc")); // for malloc
     //execCommand(_("sharedlibrary libdl")); // for dlopen
-    execCommand(_("call (void)dlopen(\"") + lib + _("\", " STRINGIFY(RTLD_NOW) ")"),
+    execCommand(_("call (void)dlopen(\"") + GdbMi::escapeCString(lib) + _("\", " STRINGIFY(RTLD_NOW) ")"),
         CB(handleDebuggingHelperSetup));
     //execCommand(_("sharedlibrary ") + dotEscape(lib));
     m_debuggingHelperState = DebuggingHelperLoadTried;
@@ -3863,10 +3864,10 @@ void GdbEngine::tryLoadDebuggingHelpers()
     QString flag = QString::number(RTLD_NOW);
     execCommand(_("sharedlibrary libc")); // for malloc
     execCommand(_("sharedlibrary libdl")); // for dlopen
-    execCommand(_("call (void*)dlopen(\"") + lib + _("\", " STRINGIFY(RTLD_NOW) ")"),
+    execCommand(_("call (void*)dlopen(\"") + GdbMi::escapeCString(lib) + _("\", " STRINGIFY(RTLD_NOW) ")"),
         CB(handleDebuggingHelperSetup));
     // some older systems like CentOS 4.6 prefer this:
-    execCommand(_("call (void*)__dlopen(\"") + lib + _("\", " STRINGIFY(RTLD_NOW) ")"),
+    execCommand(_("call (void*)__dlopen(\"") + GdbMi::escapeCString(lib) + _("\", " STRINGIFY(RTLD_NOW) ")"),
         CB(handleDebuggingHelperSetup));
     execCommand(_("sharedlibrary ") + dotEscape(lib));
 #endif
diff --git a/src/plugins/debugger/gdbmi.cpp b/src/plugins/debugger/gdbmi.cpp
index 4cbd53ab1fed4bd2e6476d5bba5151314ad8af8a..e2fd7e7a25a67ec2e7ca9a0873daff134bd7363b 100644
--- a/src/plugins/debugger/gdbmi.cpp
+++ b/src/plugins/debugger/gdbmi.cpp
@@ -34,6 +34,8 @@
 #include <QtCore/QByteArray>
 #include <QtCore/QTextStream>
 
+#include <ctype.h>
+
 namespace Debugger {
 namespace Internal {
 
@@ -44,7 +46,7 @@ QTextStream &operator<<(QTextStream &os, const GdbMi &mi)
 
 void GdbMi::parseResultOrValue(const char *&from, const char *to)
 {
-    while (from != to && QChar(*from).isSpace())
+    while (from != to && isspace(*from))
         ++from;
 
     //qDebug() << "parseResultOrValue: " << QByteArray(from, to - from);
@@ -74,6 +76,7 @@ QByteArray GdbMi::parseCString(const char *&from, const char *to)
     //qDebug() << "parseCString: " << QByteArray::fromUtf16(from, to - from);
     if (*from != '"') {
         qDebug() << "MI Parse Error, double quote expected";
+        ++from; // So we don't hang
         return QByteArray();
     }
     const char *ptr = from;
@@ -84,22 +87,66 @@ QByteArray GdbMi::parseCString(const char *&from, const char *to)
             result = QByteArray(from + 1, ptr - from - 2);
             break;
         }
-        if (*ptr == '\\' && ptr < to - 1)
+        if (*ptr == '\\') {
             ++ptr;
+            if (ptr == to) {
+                qDebug() << "MI Parse Error, unterminated backslash escape";
+                from = ptr; // So we don't hang
+                return QByteArray();
+            }
+        }
         ++ptr;
     }
+    from = ptr;
 
-    if (result.contains('\\')) {
-        if (result.contains("\\032\\032"))
-            result.clear();
-        else {
-            result = result.replace("\\n", "\n");
-            result = result.replace("\\t", "\t");
-            result = result.replace("\\\"", "\"");
-        }
+    int idx = result.indexOf('\\');
+    if (idx >= 0) {
+        char *dst = result.data() + idx;
+        const char *src = dst + 1, *end = result.data() + result.length();
+        do {
+            char c = *src++;
+            switch (c) {
+                case 'a': *dst++ = '\a'; break;
+                case 'b': *dst++ = '\b'; break;
+                case 'f': *dst++ = '\f'; break;
+                case 'n': *dst++ = '\n'; break;
+                case 'r': *dst++ = '\r'; break;
+                case 't': *dst++ = '\t'; break;
+                case 'v': *dst++ = '\v'; break;
+                case '"': *dst++ = '"'; break;
+                case '\\': *dst++ = '\\'; break;
+                default:
+                    {
+                        int chars = 0;
+                        uchar prod = 0;
+                        forever {
+                            if (c < '0' || c > '7') {
+                                --src;
+                                break;
+                            }
+                            prod = prod * 8 + c - '0';
+                            if (++chars == 3 || src == end)
+                                break;
+                            c = *src++;
+                        }
+                        if (!chars) {
+                            qDebug() << "MI Parse Error, unrecognized backslash escape";
+                            return QByteArray();
+                        }
+                        *dst++ = prod;
+                    }
+            }
+            while (src != end) {
+                char c = *src++;
+                if (c == '\\')
+                    break;
+                *dst++ = c;
+            }
+        } while (src != end);
+        *dst = 0;
+        result.truncate(dst - result.data());
     }
 
-    from = ptr;
     return result;
 }
 
@@ -203,10 +250,50 @@ void GdbMi::dumpChildren(QByteArray * str, bool multiline, int indent) const
     }
 }
 
-static QByteArray escaped(QByteArray ba)
+class MyString : public QString {
+public:
+    ushort at(int i) const { return constData()[i].unicode(); }
+};
+
+template<class ST, typename CT>
+inline ST escapeCStringTpl(const ST &ba)
+{
+    ST ret;
+    ret.reserve(ba.length() * 2);
+    for (int i = 0; i < ba.length(); ++i) {
+        CT c = ba.at(i);
+        switch (c) {
+            case '\\': ret += "\\\\"; break;
+            case '\a': ret += "\\a"; break;
+            case '\b': ret += "\\b"; break;
+            case '\f': ret += "\\f"; break;
+            case '\n': ret += "\\n"; break;
+            case '\r': ret += "\\r"; break;
+            case '\t': ret += "\\t"; break;
+            case '\v': ret += "\\v"; break;
+            case '"': ret += "\\\""; break;
+            default:
+                if (c < 32 || c == 127) {
+                    ret += '\\';
+                    ret += '0' + (c >> 6);
+                    ret += '0' + ((c >> 3) & 7);
+                    ret += '0' + (c & 7);
+                } else {
+                    ret += c;
+                }
+        }
+    }
+    return ret;
+}
+
+QString GdbMi::escapeCString(const QString &ba)
+{
+    return escapeCStringTpl<MyString, ushort>(static_cast<const MyString &>(ba));
+}
+
+QByteArray GdbMi::escapeCString(const QByteArray &ba)
 {
-    ba.replace("\"", "\\\"");
-    return ba;
+    return escapeCStringTpl<QByteArray, uchar>(ba);
 }
 
 QByteArray GdbMi::toString(bool multiline, int indent) const
@@ -222,7 +309,7 @@ QByteArray GdbMi::toString(bool multiline, int indent) const
         case Const: 
             if (!m_name.isEmpty())
                 result += m_name + "=";
-            result += "\"" + escaped(m_data) + "\"";
+            result += "\"" + escapeCString(m_data) + "\"";
             break;
         case Tuple:
             if (!m_name.isEmpty())
diff --git a/src/plugins/debugger/gdbmi.h b/src/plugins/debugger/gdbmi.h
index 311bef2a7ce3559dd24511341c0287da2d07d0c5..1e9731bb30362f2f46a786539a16c292922be16a 100644
--- a/src/plugins/debugger/gdbmi.h
+++ b/src/plugins/debugger/gdbmi.h
@@ -132,6 +132,8 @@ private:
     friend class GdbEngine;
 
     static QByteArray parseCString(const char *&from, const char *to);
+    static QByteArray escapeCString(const QByteArray &ba);
+    static QString escapeCString(const QString &ba);
     void parseResultOrValue(const char *&from, const char *to);
     void parseValue(const char *&from, const char *to);
     void parseTuple(const char *&from, const char *to);
diff --git a/src/plugins/debugger/watchutils.cpp b/src/plugins/debugger/watchutils.cpp
index 5693c2c2159adfa034117f184ca3df28b498b724..407ada9cadfbb74c7421917257817a11f5fa1086 100644
--- a/src/plugins/debugger/watchutils.cpp
+++ b/src/plugins/debugger/watchutils.cpp
@@ -136,6 +136,7 @@ bool hasSideEffects(const QString &exp)
     return exp.contains(QLatin1String("-="))
         || exp.contains(QLatin1String("+="))
         || exp.contains(QLatin1String("/="))
+        || exp.contains(QLatin1String("%="))
         || exp.contains(QLatin1String("*="))
         || exp.contains(QLatin1String("&="))
         || exp.contains(QLatin1String("|="))
diff --git a/tests/auto/debugger/main.cpp b/tests/auto/debugger/main.cpp
index 4e7eeeeb61fa34ae6daa528a1f968890c98a6869..afb51a38c0118d821ac1f58099995172bd48a021 100644
--- a/tests/auto/debugger/main.cpp
+++ b/tests/auto/debugger/main.cpp
@@ -52,7 +52,7 @@ static const char test11[] =
      "{name=\"0\",value=\"one\",type=\"QByteArray\"}]";
 
 static const char test12[] =
-    "[{iname=\"local.hallo\",value=\"\\\"\\\"\",type=\"QByteArray\","
+    "[{iname=\"local.hallo\",value=\"\\\"\\\\\\00382\\t\\377\",type=\"QByteArray\","
      "numchild=\"0\"}]";
 
 class tst_Debugger : public QObject