diff --git a/src/plugins/cmakeprojectmanager/cmakeproject.cpp b/src/plugins/cmakeprojectmanager/cmakeproject.cpp
index e05614029c31d7c6c09d8b73d0086222bbfd7aa4..455c6e87095ca562cfa470fe656728544a7c267f 100644
--- a/src/plugins/cmakeprojectmanager/cmakeproject.cpp
+++ b/src/plugins/cmakeprojectmanager/cmakeproject.cpp
@@ -500,7 +500,7 @@ void CMakeProject::setUserEnvironmentChanges(const QString &buildConfig, const Q
     QStringList list = EnvironmentItem::toStringList(diff);
     if (list == value(buildConfig, "userEnvironmentChanges"))
         return;
-    setValue(buildConfig, "userEnvironmentChanges", EnvironmentItem::toStringList(diff));
+    setValue(buildConfig, "userEnvironmentChanges", list);
     emit environmentChanged(buildConfig);
 }
 
diff --git a/src/plugins/cppeditor/cppeditor.cpp b/src/plugins/cppeditor/cppeditor.cpp
index 5bea06a0453c49e1ff3ef337382fd972c7cde7fb..597a2769e8508e50056fb98351715c610021c168 100644
--- a/src/plugins/cppeditor/cppeditor.cpp
+++ b/src/plugins/cppeditor/cppeditor.cpp
@@ -527,8 +527,6 @@ CPPEditorEditable::CPPEditorEditable(CPPEditor *editor)
 
 CPPEditor::CPPEditor(QWidget *parent)
     : TextEditor::BaseTextEditor(parent)
-    , m_mouseNavigationEnabled(true)
-    , m_showingLink(false)
     , m_currentRenameSelection(-1)
     , m_inRename(false)
 {
@@ -1073,7 +1071,7 @@ void CPPEditor::switchDeclarationDefinition()
 }
 
 CPPEditor::Link CPPEditor::findLinkAt(const QTextCursor &cursor,
-                                      bool lookupDefinition)
+                                      bool resolveTarget)
 {
     Link link;
 
@@ -1153,7 +1151,7 @@ CPPEditor::Link CPPEditor::findLinkAt(const QTextCursor &cursor,
 
         if (Symbol *symbol = result.second) {
             Symbol *def = 0;
-            if (lookupDefinition && !lastSymbol->isFunction())
+            if (resolveTarget && !lastSymbol->isFunction())
                 def = findDefinition(symbol);
 
             link = linkToSymbol(def ? def : symbol);
@@ -1190,7 +1188,7 @@ CPPEditor::Link CPPEditor::findLinkAt(const QTextCursor &cursor,
 
 void CPPEditor::jumpToDefinition()
 {
-    openCppEditorAt(findLinkAt(textCursor()));
+    openLink(findLinkAt(textCursor()));
 }
 
 Symbol *CPPEditor::findDefinition(Symbol *symbol)
@@ -1342,68 +1340,6 @@ void CPPEditor::contextMenuEvent(QContextMenuEvent *e)
     delete menu;
 }
 
-void CPPEditor::mouseMoveEvent(QMouseEvent *e)
-{
-    bool linkFound = false;
-
-    if (m_mouseNavigationEnabled && e->modifiers() & Qt::ControlModifier) {
-        // Link emulation behaviour for 'go to definition'
-        const QTextCursor cursor = cursorForPosition(e->pos());
-
-        // Check that the mouse was actually on the text somewhere
-        bool onText = cursorRect(cursor).right() >= e->x();
-        if (!onText) {
-            QTextCursor nextPos = cursor;
-            nextPos.movePosition(QTextCursor::Right);
-            onText = cursorRect(nextPos).right() >= e->x();
-        }
-
-        const Link link = findLinkAt(cursor, false);
-
-        if (onText && !link.fileName.isEmpty()) {
-            showLink(link);
-            linkFound = true;
-        }
-    }
-
-    if (!linkFound)
-        clearLink();
-
-    TextEditor::BaseTextEditor::mouseMoveEvent(e);
-}
-
-void CPPEditor::mouseReleaseEvent(QMouseEvent *e)
-{
-    if (m_mouseNavigationEnabled && e->modifiers() & Qt::ControlModifier
-        && !(e->modifiers() & Qt::ShiftModifier)
-        && e->button() == Qt::LeftButton) {
-
-        const QTextCursor cursor = cursorForPosition(e->pos());
-        if (openCppEditorAt(findLinkAt(cursor))) {
-            clearLink();
-            e->accept();
-            return;
-        }
-    }
-
-    TextEditor::BaseTextEditor::mouseReleaseEvent(e);
-}
-
-void CPPEditor::leaveEvent(QEvent *e)
-{
-    clearLink();
-    TextEditor::BaseTextEditor::leaveEvent(e);
-}
-
-void CPPEditor::keyReleaseEvent(QKeyEvent *e)
-{
-    // Clear link emulation when Ctrl is released
-    if (e->key() == Qt::Key_Control)
-        clearLink();
-
-    TextEditor::BaseTextEditor::keyReleaseEvent(e);
-}
-
 void CPPEditor::keyPressEvent(QKeyEvent *e)
 {
     if (m_currentRenameSelection == -1) {
@@ -1491,29 +1427,6 @@ void CPPEditor::keyPressEvent(QKeyEvent *e)
     TextEditor::BaseTextEditor::keyPressEvent(e);
 }
 
-void CPPEditor::showLink(const Link &link)
-{
-    QTextEdit::ExtraSelection sel;
-    sel.cursor = textCursor();
-    sel.cursor.setPosition(link.pos);
-    sel.cursor.setPosition(link.pos + link.length, QTextCursor::KeepAnchor);
-    sel.format = m_linkFormat;
-    sel.format.setFontUnderline(true);
-    setExtraSelections(OtherSelection, QList<QTextEdit::ExtraSelection>() << sel);
-    viewport()->setCursor(Qt::PointingHandCursor);
-    m_showingLink = true;
-}
-
-void CPPEditor::clearLink()
-{
-    if (!m_showingLink)
-        return;
-
-    setExtraSelections(OtherSelection, QList<QTextEdit::ExtraSelection>());
-    viewport()->setCursor(Qt::IBeamCursor);
-    m_showingLink = false;
-}
-
 QList<int> CPPEditorEditable::context() const
 {
     return m_context;
@@ -1557,17 +1470,10 @@ void CPPEditor::setFontSettings(const TextEditor::FontSettings &fs)
     highlighter->setFormats(formats.constBegin(), formats.constEnd());
     highlighter->rehighlight();
 
-    m_linkFormat = fs.toTextCharFormat(QLatin1String(TextEditor::Constants::C_LINK));
     m_occurrencesFormat = fs.toTextCharFormat(QLatin1String(TextEditor::Constants::C_OCCURRENCES));
     m_occurrenceRenameFormat = fs.toTextCharFormat(QLatin1String(TextEditor::Constants::C_OCCURRENCES_RENAME));
 }
 
-void CPPEditor::setDisplaySettings(const TextEditor::DisplaySettings &ds)
-{
-    TextEditor::BaseTextEditor::setDisplaySettings(ds);
-    m_mouseNavigationEnabled = ds.m_mouseNavigation;
-}
-
 void CPPEditor::unCommentSelection()
 {
     Core::Utils::unCommentSelection(this);
diff --git a/src/plugins/cppeditor/cppeditor.h b/src/plugins/cppeditor/cppeditor.h
index 27991a550f3831ab4fac9e4c59501398fbabca6e..40e2e71972f22517d492875c3892b727b66a76ae 100644
--- a/src/plugins/cppeditor/cppeditor.h
+++ b/src/plugins/cppeditor/cppeditor.h
@@ -193,7 +193,6 @@ public:
 
 public Q_SLOTS:
     virtual void setFontSettings(const TextEditor::FontSettings &);
-    virtual void setDisplaySettings(const TextEditor::DisplaySettings &);
     void setSortedMethodOverview(bool sort);
     void switchDeclarationDefinition();
     void jumpToDefinition();
@@ -208,10 +207,6 @@ public Q_SLOTS:
 protected:
     bool event(QEvent *e);
     void contextMenuEvent(QContextMenuEvent *);
-    void mouseMoveEvent(QMouseEvent *);
-    void mouseReleaseEvent(QMouseEvent *);
-    void leaveEvent(QEvent *);
-    void keyReleaseEvent(QKeyEvent *);
     void keyPressEvent(QKeyEvent *);
 
     TextEditor::BaseTextEditorEditable *createEditableInterface();
@@ -261,36 +256,11 @@ private:
                                const QString &text = QString());
     void abortRename();
 
-    struct Link
-    {
-        Link(const QString &fileName = QString(),
-             int line = 0,
-             int column = 0)
-            : pos(-1)
-            , length(-1)
-            , fileName(fileName)
-            , line(line)
-            , column(column)
-        {}
-
-        int pos;           // Link position
-        int length;        // Link length
-
-        QString fileName;  // Target file
-        int line;          // Target line
-        int column;        // Target column
-    };
-
-    void showLink(const Link &);
-    void clearLink();
-
-    Link findLinkAt(const QTextCursor &, bool lookupDefinition = true);
-    static Link linkToSymbol(CPlusPlus::Symbol *symbol);
+    Link findLinkAt(const QTextCursor &, bool resolveTarget = true);
+    bool openLink(const Link &link) { return openCppEditorAt(link); }
     bool openCppEditorAt(const Link &);
 
-    bool m_mouseNavigationEnabled;
-    bool m_showingLink;
-    QTextCharFormat m_linkFormat;
+    static Link linkToSymbol(CPlusPlus::Symbol *symbol);
 
     CppTools::CppModelManagerInterface *m_modelManager;
 
diff --git a/src/plugins/cppeditor/cpphighlighter.cpp b/src/plugins/cppeditor/cpphighlighter.cpp
index 95e25b4b2573db244b2d9b9ff21975939026ac7c..d2cda6f77df79a7287db641d0b8fed866b0b5aac 100644
--- a/src/plugins/cppeditor/cpphighlighter.cpp
+++ b/src/plugins/cppeditor/cpphighlighter.cpp
@@ -73,6 +73,8 @@ void CppHighlighter::highlightBlock(const QString &text)
             userData->setCollapseMode(TextBlockUserData::NoCollapse);
         }
         TextEditDocumentLayout::clearParentheses(currentBlock());
+        if (text.length()) // the empty line can still contain whitespace
+            setFormat(0, text.length(), visualSpaceFormat);
         return;
     }
 
@@ -171,7 +173,7 @@ void CppHighlighter::highlightBlock(const QString &text)
     }
 
     // mark the trailing white spaces
-    if (! tokens.isEmpty()) {
+    {
         const SimpleToken tk = tokens.last();
         const int lastTokenEnd = tk.position() + tk.length();
         if (text.length() > lastTokenEnd)
diff --git a/src/plugins/debugger/debugger.pro b/src/plugins/debugger/debugger.pro
index 3cdc4f16f56a132d7c188422dc9d60c1b9b3b46f..c9be97b726063195c1588819f6bd03e4fa669681 100644
--- a/src/plugins/debugger/debugger.pro
+++ b/src/plugins/debugger/debugger.pro
@@ -87,5 +87,7 @@ include(cdb/cdb.pri)
 include(gdb/gdb.pri)
 include(script/script.pri)
 include(tcf/tcf.pri)
+include(symbian/symbian.pri)
 include(shared/shared.pri)
+
 OTHER_FILES += Debugger.pluginspec
diff --git a/src/plugins/debugger/debuggermanager.cpp b/src/plugins/debugger/debuggermanager.cpp
index a17056ec1f865ba66c2f5031ea9e06e5c01c69b2..b4a5c84a7ee71c28a106aa8b3e200471d4a9c7ca 100644
--- a/src/plugins/debugger/debuggermanager.cpp
+++ b/src/plugins/debugger/debuggermanager.cpp
@@ -103,6 +103,8 @@ namespace Internal {
 
 IDebuggerEngine *createGdbEngine(DebuggerManager *parent, QList<Core::IOptionsPage*> *);
 
+IDebuggerEngine *createSymbianEngine(DebuggerManager *parent, QList<Core::IOptionsPage*> *);
+
 QDebug operator<<(QDebug str, const DebuggerStartParameters &p)
 {
     QDebug nospace = str.nospace();
diff --git a/src/plugins/debugger/gdb/gdbengine.cpp b/src/plugins/debugger/gdb/gdbengine.cpp
index 89669c9df5e23c42708b513c2320475794f03220..055d8adfdf21238a0b5b7526eb645f7e5110218a 100644
--- a/src/plugins/debugger/gdb/gdbengine.cpp
+++ b/src/plugins/debugger/gdb/gdbengine.cpp
@@ -144,7 +144,7 @@ static QByteArray parsePlainConsoleStream(const GdbResultRecord &record)
 //
 ///////////////////////////////////////////////////////////////////////
 
-GdbEngine::GdbEngine(DebuggerManager *parent) :
+GdbEngine::GdbEngine(DebuggerManager *parent, GdbProcessBase *gdbProc) :
 #ifdef Q_OS_WIN // Do injection loading with MinGW (call loading does not work with 64bit)
     m_dumperInjectionLoad(true),
 #else
@@ -153,6 +153,7 @@ GdbEngine::GdbEngine(DebuggerManager *parent) :
     q(parent),
     qq(parent->engineInterface())
 {
+    m_gdbProc = gdbProc;
     m_stubProc.setMode(Core::Utils::ConsoleProcess::Debug);
 #ifdef Q_OS_UNIX
     m_stubProc.setSettings(Core::ICore::instance()->settings());
@@ -164,19 +165,20 @@ GdbEngine::GdbEngine(DebuggerManager *parent) :
 GdbEngine::~GdbEngine()
 {
     // prevent sending error messages afterwards
-    m_gdbProc.disconnect(this);
+    m_gdbProc->disconnect(this);
+    delete m_gdbProc;
 }
 
 void GdbEngine::initializeConnections()
 {
     // Gdb Process interaction
-    connect(&m_gdbProc, SIGNAL(error(QProcess::ProcessError)),
+    connect(m_gdbProc, SIGNAL(error(QProcess::ProcessError)),
         this, SLOT(gdbProcError(QProcess::ProcessError)));
-    connect(&m_gdbProc, SIGNAL(readyReadStandardOutput()),
+    connect(m_gdbProc, SIGNAL(readyReadStandardOutput()),
         this, SLOT(readGdbStandardOutput()));
-    connect(&m_gdbProc, SIGNAL(readyReadStandardError()),
+    connect(m_gdbProc, SIGNAL(readyReadStandardError()),
         this, SLOT(readGdbStandardError()));
-    connect(&m_gdbProc, SIGNAL(finished(int, QProcess::ExitStatus)),
+    connect(m_gdbProc, SIGNAL(finished(int, QProcess::ExitStatus)),
         q, SLOT(exitDebugger()));
 
     connect(&m_stubProc, SIGNAL(processError(QString)),
@@ -614,7 +616,7 @@ void GdbEngine::stubError(const QString &msg)
 
 void GdbEngine::readGdbStandardError()
 {
-    qWarning() << "Unexpected gdb stderr:" << m_gdbProc.readAllStandardError();
+    qWarning() << "Unexpected gdb stderr:" << m_gdbProc->readAllStandardError();
 }
 
 void GdbEngine::readGdbStandardOutput()
@@ -622,7 +624,7 @@ void GdbEngine::readGdbStandardOutput()
     int newstart = 0;
     int scan = m_inbuffer.size();
 
-    m_inbuffer.append(m_gdbProc.readAllStandardOutput());
+    m_inbuffer.append(m_gdbProc->readAllStandardOutput());
 
     while (newstart < m_inbuffer.size()) {
         int start = newstart;
@@ -651,7 +653,7 @@ void GdbEngine::interruptInferior()
 {
     qq->notifyInferiorStopRequested();
 
-    if (m_gdbProc.state() == QProcess::NotRunning) {
+    if (m_gdbProc->state() == QProcess::NotRunning) {
         debugMessage(_("TRYING TO INTERRUPT INFERIOR WITHOUT RUNNING GDB"));
         qq->notifyInferiorExited();
         return;
@@ -698,7 +700,7 @@ void GdbEngine::postCommand(const QString &command, GdbCommandFlags flags,
                             GdbCommandCallback callback, const char *callbackName,
                             const QVariant &cookie)
 {
-    if (m_gdbProc.state() == QProcess::NotRunning) {
+    if (m_gdbProc->state() == QProcess::NotRunning) {
         debugMessage(_("NO GDB PROCESS RUNNING, CMD IGNORED: ") + command);
         return;
     }
@@ -742,7 +744,7 @@ void GdbEngine::flushCommand(GdbCommand &cmd)
     if (cmd.flags & EmbedToken)
         cmd.command = cmd.command.arg(currentToken());
 
-    m_gdbProc.write(cmd.command.toLatin1() + "\r\n");
+    m_gdbProc->write(cmd.command.toLatin1() + "\r\n");
     //emit gdbInputAvailable(QString(), "         " +  currentTime());
     //emit gdbInputAvailable(QString(), "[" + currentTime() + "]    " + cmd.command);
     emit gdbInputAvailable(LogInput, cmd.command);
@@ -829,12 +831,12 @@ void GdbEngine::handleResultRecord(const GdbResultRecord &record)
 
 void GdbEngine::executeDebuggerCommand(const QString &command)
 {
-    if (m_gdbProc.state() == QProcess::NotRunning) {
+    if (m_gdbProc->state() == QProcess::NotRunning) {
         debugMessage(_("NO GDB PROCESS RUNNING, PLAIN CMD IGNORED: ") + command);
         return;
     }
 
-    m_gdbProc.write(command.toLocal8Bit() + "\r\n");
+    m_gdbProc->write(command.toLocal8Bit() + "\r\n");
 }
 
 void GdbEngine::handleTargetCore(const GdbResultRecord &, const QVariant &)
@@ -1434,15 +1436,15 @@ void GdbEngine::detachDebugger()
 
 void GdbEngine::exitDebugger()
 {
-    debugMessage(_("GDBENGINE EXITDEBUGGER: %1").arg(m_gdbProc.state()));
-    if (m_gdbProc.state() == QProcess::Starting) {
+    debugMessage(_("GDBENGINE EXITDEBUGGER: %1").arg(m_gdbProc->state()));
+    if (m_gdbProc->state() == QProcess::Starting) {
         debugMessage(_("WAITING FOR GDB STARTUP TO SHUTDOWN: %1")
-            .arg(m_gdbProc.state()));
-        m_gdbProc.waitForStarted();
+            .arg(m_gdbProc->state()));
+        m_gdbProc->waitForStarted();
     }
-    if (m_gdbProc.state() == QProcess::Running) {
+    if (m_gdbProc->state() == QProcess::Running) {
         debugMessage(_("WAITING FOR RUNNING GDB TO SHUTDOWN: %1")
-            .arg(m_gdbProc.state()));
+            .arg(m_gdbProc->state()));
         if (q->status() != DebuggerInferiorStopped
             && q->status() != DebuggerProcessStartingUp) {
             QTC_ASSERT(q->status() == DebuggerInferiorRunning,
@@ -1455,17 +1457,17 @@ void GdbEngine::exitDebugger()
             postCommand(_("kill"));
         postCommand(_("-gdb-exit"), CB(handleExit));
         // 20s can easily happen when loading webkit debug information
-        if (!m_gdbProc.waitForFinished(20000)) {
+        if (!m_gdbProc->waitForFinished(20000)) {
             debugMessage(_("FORCING TERMINATION: %1")
-                .arg(m_gdbProc.state()));
-            m_gdbProc.terminate();
-            m_gdbProc.waitForFinished(20000);
+                .arg(m_gdbProc->state()));
+            m_gdbProc->terminate();
+            m_gdbProc->waitForFinished(20000);
         }
     }
-    if (m_gdbProc.state() != QProcess::NotRunning) {
+    if (m_gdbProc->state() != QProcess::NotRunning) {
         debugMessage(_("PROBLEM STOPPING DEBUGGER: STATE %1")
-            .arg(m_gdbProc.state()));
-        m_gdbProc.kill();
+            .arg(m_gdbProc->state()));
+        m_gdbProc->kill();
     }
 
     m_outputCollector.shutdown();
@@ -1487,9 +1489,9 @@ bool GdbEngine::startDebugger(const QSharedPointer<DebuggerStartParameters> &sp)
 
     QStringList gdbArgs;
 
-    if (m_gdbProc.state() != QProcess::NotRunning) {
-        debugMessage(_("GDB IS ALREADY RUNNING, STATE: %1").arg(m_gdbProc.state()));
-        m_gdbProc.kill();
+    if (m_gdbProc->state() != QProcess::NotRunning) {
+        debugMessage(_("GDB IS ALREADY RUNNING, STATE: %1").arg(m_gdbProc->state()));
+        m_gdbProc->kill();
         return false;
     }
 
@@ -1529,16 +1531,16 @@ bool GdbEngine::startDebugger(const QSharedPointer<DebuggerStartParameters> &sp)
         gdbArgs.prepend(_("--tty=") + m_outputCollector.serverName());
 
         if (!sp->workingDir.isEmpty())
-            m_gdbProc.setWorkingDirectory(sp->workingDir);
+            m_gdbProc->setWorkingDirectory(sp->workingDir);
         if (!sp->environment.isEmpty())
-            m_gdbProc.setEnvironment(sp->environment);
+            m_gdbProc->setEnvironment(sp->environment);
     }
 
     #if 0
     qDebug() << "Command:" << q->settings()->m_gdbCmd;
-    qDebug() << "WorkingDirectory:" << m_gdbProc.workingDirectory();
+    qDebug() << "WorkingDirectory:" << m_gdbProc->workingDirectory();
     qDebug() << "ScriptFile:" << q->settings()->m_scriptFile;
-    qDebug() << "Environment:" << m_gdbProc.environment();
+    qDebug() << "Environment:" << m_gdbProc->environment();
     qDebug() << "Arguments:" << gdbArgs;
     qDebug() << "BuildDir:" << sp->buildDir;
     qDebug() << "ExeFile:" << sp->executable;
@@ -1546,10 +1548,10 @@ bool GdbEngine::startDebugger(const QSharedPointer<DebuggerStartParameters> &sp)
 
     QString loc = theDebuggerStringSetting(GdbLocation);
     q->showStatusMessage(tr("Starting Debugger: ") + loc + _c(' ') + gdbArgs.join(_(" ")));
-    m_gdbProc.start(loc, gdbArgs);
-    if (!m_gdbProc.waitForStarted()) {
+    m_gdbProc->start(loc, gdbArgs);
+    if (!m_gdbProc->waitForStarted()) {
         QMessageBox::critical(q->mainWindow(), tr("Debugger Startup Failure"),
-                              tr("Cannot start debugger: %1").arg(m_gdbProc.errorString()));
+                              tr("Cannot start debugger: %1").arg(m_gdbProc->errorString()));
         m_outputCollector.shutdown();
         m_stubProc.blockSignals(true);
         m_stubProc.stop();
@@ -4198,7 +4200,7 @@ void GdbEngine::handleFetchDisassemblerByAddress0(const GdbResultRecord &record,
 IDebuggerEngine *createGdbEngine(DebuggerManager *parent, QList<Core::IOptionsPage*> *opts)
 {
     opts->push_back(new GdbOptionsPage);
-    return new GdbEngine(parent);
+    return new GdbEngine(parent, new GdbProcess);
 }
 
 } // namespace Internal
diff --git a/src/plugins/debugger/gdb/gdbengine.h b/src/plugins/debugger/gdb/gdbengine.h
index 2694ec01fbd8b182d8b5f2665365084f6e800f40..88eadb4c0953065dec8b8b44543920e86e111702 100644
--- a/src/plugins/debugger/gdb/gdbengine.h
+++ b/src/plugins/debugger/gdb/gdbengine.h
@@ -32,6 +32,7 @@
 
 #include "idebuggerengine.h"
 #include "gdbmi.h"
+#include "gdbprocessbase.h"
 #include "outputcollector.h"
 #include "watchutils.h"
 
@@ -56,6 +57,7 @@ QT_END_NAMESPACE
 namespace Debugger {
 namespace Internal {
 
+
 class DebuggerManager;
 class IDebuggerManagerAccessForEngines;
 class GdbResultRecord;
@@ -72,13 +74,46 @@ enum DebuggingHelperState
     DebuggingHelperUnavailable,
 };
 
+class GdbProcess : public GdbProcessBase
+{
+public:
+    GdbProcess(QObject *parent = 0)
+        : GdbProcessBase(parent)
+    {
+        connect(&m_proc, SIGNAL(error(QProcess::ProcessError)),
+            this, SIGNAL(error(QProcess::ProcessError)));
+        connect(&m_proc, SIGNAL(readyReadStandardOutput()),
+            this, SIGNAL(readyReadStandardOutput()));
+        connect(&m_proc, SIGNAL(readyReadStandardError()),
+            this, SIGNAL(readyReadStandardError()));
+        connect(&m_proc, SIGNAL(finished(int, QProcess::ExitStatus)),
+            this, SIGNAL(finished(int, QProcess::ExitStatus)));
+    }
+
+    void start(const QString &program, const QStringList &args,
+        QIODevice::OpenMode mode) { m_proc.start(program, args, mode); }
+    void kill() { m_proc.kill(); }
+    void terminate() { m_proc.terminate(); }
+    bool waitForStarted(int msecs) { return m_proc.waitForStarted(msecs); }
+    bool waitForFinished(int msecs) { return m_proc.waitForFinished(msecs); }
+    QProcess::ProcessState state() const { return m_proc.state(); }
+    QString errorString() const { return m_proc.errorString(); }
+    QByteArray readAllStandardError() { return m_proc.readAllStandardError(); }
+    QByteArray readAllStandardOutput() { return m_proc.readAllStandardOutput(); }
+    qint64 write(const char *data) { return m_proc.write(data); }
+    void setWorkingDirectory(const QString &dir) { m_proc.setWorkingDirectory(dir); }
+    void setEnvironment(const QStringList &env) { m_proc.setEnvironment(env); }
+
+private:
+    QProcess m_proc;
+};
 
 class GdbEngine : public IDebuggerEngine
 {
     Q_OBJECT
 
 public:
-    GdbEngine(DebuggerManager *parent);
+    GdbEngine(DebuggerManager *parent, GdbProcessBase *gdbProc);
     ~GdbEngine();
 
 signals:
@@ -251,7 +286,7 @@ private:
 
     QByteArray m_inbuffer;
 
-    QProcess m_gdbProc;
+    GdbProcessBase *m_gdbProc;
     QProcess m_uploadProc;
 
     Core::Utils::ConsoleProcess m_stubProc;
diff --git a/src/plugins/debugger/gdb/gdbprocessbase.h b/src/plugins/debugger/gdb/gdbprocessbase.h
new file mode 100644
index 0000000000000000000000000000000000000000..b6adfc763bb533731f3ba1f365db956a8731fd00
--- /dev/null
+++ b/src/plugins/debugger/gdb/gdbprocessbase.h
@@ -0,0 +1,74 @@
+/**************************************************************************
+**
+** 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.
+**
+**************************************************************************/
+
+#ifndef DEBUGGER_PROCESSBASE_H
+#define DEBUGGER_PROCESSBASE_H
+
+#include <QtCore/QObject>
+#include <QtCore/QProcess>
+
+namespace Debugger {
+namespace Internal {
+
+// GdbProcessBase is inherited by GdbProcess and the gdb/trk Adapter.
+// In the GdbProcess case it's just a wrapper around a QProcess running
+// gdb, in the Adapter case it's the interface to the gdb process in
+// the whole rfomm/gdb/gdbserver combo.
+class GdbProcessBase : public QObject
+{
+    Q_OBJECT
+
+public:
+    GdbProcessBase(QObject *parent = 0) : QObject(parent) {}
+
+    virtual void start(const QString &program, const QStringList &args,
+        QIODevice::OpenMode mode = QIODevice::ReadWrite) = 0;
+    virtual void kill() = 0;
+    virtual void terminate() = 0;
+    virtual bool waitForStarted(int msecs = 30000) = 0;
+    virtual bool waitForFinished(int msecs = 30000) = 0;
+    virtual QProcess::ProcessState state() const = 0;
+    virtual QString errorString() const = 0;
+    virtual QByteArray readAllStandardError() = 0;
+    virtual QByteArray readAllStandardOutput() = 0;
+    virtual qint64 write(const char *data) = 0;
+    virtual void setWorkingDirectory(const QString &dir) = 0;
+    virtual void setEnvironment(const QStringList &env) = 0;
+
+signals:
+    void error(QProcess::ProcessError);
+    void readyReadStandardOutput();
+    void readyReadStandardError();
+    void finished(int, QProcess::ExitStatus);
+};
+
+} // namespace Internal
+} // namespace Debugger
+
+#endif // DEBUGGER_PROCESSBASE_H
diff --git a/src/plugins/debugger/symbian/symbian.pri b/src/plugins/debugger/symbian/symbian.pri
new file mode 100644
index 0000000000000000000000000000000000000000..1ffb8081d4f16b6706f1f4bbdccad970739b2bd7
--- /dev/null
+++ b/src/plugins/debugger/symbian/symbian.pri
@@ -0,0 +1,14 @@
+HEADERS += \
+    $$PWD/trkclient.h \
+    $$PWD/symbianadapter.h \
+    #$$PWD/gdboptionspage.h \
+
+SOURCES += \
+    $$PWD/trkclient.cpp \
+    $$PWD/symbianadapter.cpp \
+    $$PWD/symbianengine.cpp \
+    #$$PWD/gdboptionspage.cpp \
+
+#FORMS +=  $$PWD/gdboptionspage.ui
+
+#RESOURCES += $$PWD/gdb.qrc
diff --git a/src/plugins/debugger/symbian/symbianadapter.cpp b/src/plugins/debugger/symbian/symbianadapter.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..8f66b33124209e695259042b8b9900d0709ae9fd
--- /dev/null
+++ b/src/plugins/debugger/symbian/symbianadapter.cpp
@@ -0,0 +1,1599 @@
+/**************************************************************************
+**
+** 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 "symbianadapter.h"
+
+#define TrkCB(s) TrkCallback(this, &SymbianAdapter::s)
+#define GdbCB(s) GdbCallback(this, &SymbianAdapter::s)
+
+
+/*
+fetch-register          p                       info registers
+set-register            P                       set
+binary-download         X                       load, set
+read-aux-vector         qXfer:auxv:read         info auxv
+symbol-lookup           qSymbol                 Detecting multiple threads
+attach                  vAttach                 attach
+verbose-resume          vCont                   Stepping or resuming multiple threads
+run                     vRun                    run
+software-breakpoint     Z0                      break
+hardware-breakpoint     Z1                      hbreak
+write-watchpoint        Z2                      watch
+read-watchpoint         Z3                      rwatch
+access-watchpoint       Z4                      awatch
+target-features         qXfer:features:read     set architecture
+library-info            qXfer:libraries:read    info sharedlibrary
+memory-map              qXfer:memory-map:read   info mem
+read-spu-object         qXfer:spu:read          info spu
+write-spu-object        qXfer:spu:write         info spu
+get-thread-local-
+storage-address         qGetTLSAddr             Displaying __thread variables
+supported-packets       qSupported              Remote communications parameters
+pass-signals            QPassSignals            handle signal
+hostio-close-packet     vFile:close             remote get, remote put
+hostio-open-packet      vFile:open              remote get, remote put
+hostio-pread-packet     vFile:pread             remote get, remote put
+hostio-pwrite-packet    vFile:pwrite            remote get, remote put
+hostio-unlink-packet    vFile:unlink            remote delete
+*/
+
+using namespace trk;
+
+enum { KnownRegisters = RegisterPSGdb + 1};
+
+static const char *registerNames[KnownRegisters] =
+{
+    "A1", "A2", "A3", "A4",
+    0, 0, 0, 0,
+    0, 0, 0, "AP",
+    "IP", "SP", "LR", "PC",
+    "PSTrk", 0, 0, 0,
+    0, 0, 0, 0,
+    0, "PSGdb"
+};
+
+static QByteArray dumpRegister(int n, uint value)
+{
+    QByteArray ba;
+    ba += ' ';
+    if (n < KnownRegisters && registerNames[n]) {
+        ba += registerNames[n];
+    } else {
+        ba += '#';
+        ba += QByteArray::number(n);
+    }
+    ba += "=" + hexxNumber(value);
+    return ba;
+}
+
+namespace Debugger {
+namespace Internal {
+
+trk::Endianness m_registerEndianness = LittleEndian;
+
+SymbianAdapter::SymbianAdapter()
+{
+    m_running = false;
+    m_gdbAckMode = true;
+    m_verbose = 2;
+    m_serialFrame = false;
+    m_bufferedMemoryRead = true;
+    m_rfcommDevice = "/dev/rfcomm0";
+
+    uid_t userId = getuid();
+    m_gdbServerName = QString("127.0.0.1:%1").arg(2222 + userId);
+
+    m_gdbProc.setObjectName("GDB PROCESS");
+    connectProcess(&m_gdbProc);
+    connect(&m_gdbProc, SIGNAL(readyReadStandardError()),
+        this, SLOT(handleGdbReadyReadStandardError()));
+    connect(&m_gdbProc, SIGNAL(readyReadStandardOutput()),
+        this, SLOT(handleGdbReadyReadStandardOutput()));
+
+    m_rfcommProc.setObjectName("RFCOMM PROCESS");
+    connectProcess(&m_rfcommProc);
+    connect(&m_rfcommProc, SIGNAL(readyReadStandardError()),
+        this, SLOT(handleRfcommReadyReadStandardError()));
+    connect(&m_rfcommProc, SIGNAL(readyReadStandardOutput()),
+        this, SLOT(handleRfcommReadyReadStandardOutput()));
+
+    if (m_verbose > 1)
+        m_trkDevice.setVerbose(true);
+    m_trkDevice.setSerialFrame(m_serialFrame);
+
+    connect(&m_trkDevice, SIGNAL(logMessage(QString)),
+        this, SLOT(trkLogMessage(QString)));
+}
+
+SymbianAdapter::~SymbianAdapter()
+{
+    m_gdbServer.close();
+    logMessage("Shutting down.\n", true);
+}
+
+void SymbianAdapter::trkLogMessage(const QString &msg)
+{
+    logMessage("TRK " + msg);
+}
+
+void SymbianAdapter::setGdbServerName(const QString &name)
+{
+    m_gdbServerName = name;
+}
+
+QString SymbianAdapter::gdbServerIP() const
+{
+    int pos = m_gdbServerName.indexOf(':');
+    if (pos == -1)
+        return m_gdbServerName;
+    return m_gdbServerName.left(pos);
+}
+
+uint SymbianAdapter::gdbServerPort() const
+{
+    int pos = m_gdbServerName.indexOf(':');
+    if (pos == -1)
+        return 0;
+    return m_gdbServerName.mid(pos + 1).toUInt();
+}
+
+QByteArray SymbianAdapter::trkContinueMessage()
+{
+    QByteArray ba;
+    appendInt(&ba, m_session.pid);
+    appendInt(&ba, m_session.tid);
+    return ba;
+}
+
+QByteArray SymbianAdapter::trkReadRegisterMessage()
+{
+    QByteArray ba;
+    appendByte(&ba, 0); // Register set, only 0 supported
+    appendShort(&ba, 0);
+    appendShort(&ba, RegisterCount - 1); // last register
+    appendInt(&ba, m_session.pid);
+    appendInt(&ba, m_session.tid);
+    return ba;
+}
+
+QByteArray SymbianAdapter::trkReadMemoryMessage(uint addr, uint len)
+{
+    QByteArray ba;
+    appendByte(&ba, 0x08); // Options, FIXME: why?
+    appendShort(&ba, len);
+    appendInt(&ba, addr);
+    appendInt(&ba, m_session.pid);
+    appendInt(&ba, m_session.tid);
+    return ba;
+}
+
+void SymbianAdapter::startInferior()
+{
+    QString errorMessage;
+    if (!m_trkDevice.open(m_rfcommDevice, &errorMessage)) {
+        logMessage("LOOPING");
+        QTimer::singleShot(1000, this, SLOT(startInferior()));
+        return;
+    }
+
+    m_trkDevice.sendTrkInitialPing();
+    sendTrkMessage(0x01); // Connect
+    sendTrkMessage(0x05, TrkCB(handleSupportMask));
+    sendTrkMessage(0x06, TrkCB(handleCpuType));
+    sendTrkMessage(0x04, TrkCB(handleTrkVersions)); // Versions
+    //sendTrkMessage(0x09); // Unrecognized command
+    //sendTrkMessage(0x4a, 0,
+    //    "10 " + formatString("C:\\data\\usingdlls.sisx")); // Open File
+    //sendTrkMessage(0x4B, 0, "00 00 00 01 73 1C 3A C8"); // Close File
+
+    QByteArray ba;
+    appendByte(&ba, 0); // ?
+    appendByte(&ba, 0); // ?
+    appendByte(&ba, 0); // ?
+
+    QByteArray file("C:\\sys\\bin\\filebrowseapp.exe");
+    appendString(&ba, file, TargetByteOrder);
+    sendTrkMessage(0x40, TrkCB(handleCreateProcess), ba); // Create Item
+    //sendTrkMessage(TRK_WRITE_QUEUE_NOOP_CODE, TrkCB(startGdbServer));
+}
+
+void SymbianAdapter::logMessage(const QString &msg, bool force)
+{
+    if (m_verbose || force)
+        emit output(QString(), msg);
+}
+
+//
+// Gdb
+//
+void SymbianAdapter::handleGdbConnection()
+{
+    logMessage("HANDLING GDB CONNECTION");
+
+    m_gdbConnection = m_gdbServer.nextPendingConnection();
+    connect(m_gdbConnection, SIGNAL(disconnected()),
+            m_gdbConnection, SLOT(deleteLater()));
+    connect(m_gdbConnection, SIGNAL(readyRead()),
+            this, SLOT(readGdbServerCommand()));
+}
+
+static inline QString msgGdbPacket(const QString &p)
+{
+    return QLatin1String("gdb:                              ") + p;
+}
+
+void SymbianAdapter::readGdbServerCommand()
+{
+    QByteArray packet = m_gdbConnection->readAll();
+    m_gdbReadBuffer.append(packet);
+
+    logMessage("gdb: -> " + QString::fromAscii(packet));
+    if (packet != m_gdbReadBuffer)
+        logMessage("buffer: " + m_gdbReadBuffer);
+
+    QByteArray &ba = m_gdbReadBuffer;
+    while (ba.size()) {
+        char code = ba.at(0);
+        ba = ba.mid(1);
+
+        if (code == '+') {
+            //logMessage("ACK");
+            continue;
+        }
+
+        if (code == '-') {
+            logMessage("NAK: Retransmission requested");
+            continue;
+        }
+
+        if (code == char(0x03)) {
+            logMessage("INTERRUPT RECEIVED");
+            interruptInferior();
+            continue;
+        }
+
+        if (code != '$') {
+            logMessage("Broken package (2) " + quoteUnprintableLatin1(ba)
+                + hexNumber(code));
+            continue;
+        }
+
+        int pos = ba.indexOf('#');
+        if (pos == -1) {
+            logMessage("Invalid checksum format in "
+                + quoteUnprintableLatin1(ba));
+            continue;
+        }
+
+        bool ok = false;
+        uint checkSum = ba.mid(pos + 1, 2).toUInt(&ok, 16);
+        if (!ok) {
+            logMessage("Invalid checksum format 2 in "
+                + quoteUnprintableLatin1(ba));
+            return;
+        }
+
+        //logMessage(QString("Packet checksum: %1").arg(checkSum));
+        byte sum = 0;
+        for (int i = 0; i < pos; ++i)
+            sum += ba.at(i);
+
+        if (sum != checkSum) {
+            logMessage(QString("ERROR: Packet checksum wrong: %1 %2 in "
+                + quoteUnprintableLatin1(ba)).arg(checkSum).arg(sum));
+        }
+
+        QByteArray cmd = ba.left(pos);
+        ba.remove(0, pos + 3);
+        handleGdbServerCommand(cmd);
+    }
+}
+
+bool SymbianAdapter::sendGdbServerPacket(const QByteArray &packet, bool doFlush)
+{
+    if (!m_gdbConnection) {
+        logMessage(QString::fromLatin1("Cannot write to gdb: No connection (%1)")
+            .arg(QString::fromLatin1(packet)), true);
+        return false;
+    }
+    if (m_gdbConnection->state() != QAbstractSocket::ConnectedState) {
+        logMessage(QString::fromLatin1("Cannot write to gdb: Not connected (%1)")
+            .arg(QString::fromLatin1(packet)), true);
+        return false;
+    }
+    if (m_gdbConnection->write(packet) == -1) {
+        logMessage(QString::fromLatin1("Cannot write to gdb: %1 (%2)")
+            .arg(m_gdbConnection->errorString()).arg(QString::fromLatin1(packet)), true);
+        return false;
+    }
+    if (doFlush)
+        m_gdbConnection->flush();
+    return true;
+}
+
+void SymbianAdapter::sendGdbServerAck()
+{
+    if (!m_gdbAckMode)
+        return;
+    QByteArray packet = "+";
+    logMessage("gdb: <- " + packet);
+    sendGdbServerPacket(packet, false);
+}
+
+void SymbianAdapter::sendGdbServerMessage(const QByteArray &msg, const QByteArray &logNote)
+{
+    byte sum = 0;
+    for (int i = 0; i != msg.size(); ++i)
+        sum += msg.at(i);
+
+    char checkSum[30];
+    qsnprintf(checkSum, sizeof(checkSum) - 1, "%02x ", sum);
+
+    //logMessage(QString("Packet checksum: %1").arg(sum));
+
+    QByteArray packet;
+    packet.append("$");
+    packet.append(msg);
+    packet.append('#');
+    packet.append(checkSum);
+    int pad = qMax(0, 24 - packet.size());
+    logMessage("gdb: <- " + packet + QByteArray(pad, ' ') + logNote);
+    sendGdbServerPacket(packet, true);
+}
+
+void SymbianAdapter::sendGdbServerMessageAfterTrkResponse(const QByteArray &msg,
+    const QByteArray &logNote)
+{
+    QByteArray ba = msg + char(1) + logNote;
+    sendTrkMessage(TRK_WRITE_QUEUE_NOOP_CODE, TrkCB(reportToGdb), "", ba); // Answer gdb
+}
+
+void SymbianAdapter::reportToGdb(const TrkResult &result)
+{
+    QByteArray message = result.cookie.toByteArray();
+    QByteArray note;
+    int pos = message.lastIndexOf(char(1)); // HACK
+    if (pos != -1) {
+        note = message.mid(pos + 1);
+        message = message.left(pos);
+    }
+    message.replace("@CODESEG@", hexNumber(m_session.codeseg));
+    message.replace("@DATASEG@", hexNumber(m_session.dataseg));
+    message.replace("@PID@", hexNumber(m_session.pid));
+    message.replace("@TID@", hexNumber(m_session.tid));
+    sendGdbServerMessage(message, note);
+}
+
+QByteArray SymbianAdapter::trkBreakpointMessage(uint addr, uint len, bool armMode)
+{
+    QByteArray ba;
+    appendByte(&ba, 0x82);  // unused option
+    appendByte(&ba, armMode /*bp.mode == ArmMode*/ ? 0x00 : 0x01);
+    appendInt(&ba, addr);
+    appendInt(&ba, len);
+    appendInt(&ba, 0x00000001);
+    appendInt(&ba, m_session.pid);
+    appendInt(&ba, 0xFFFFFFFF);
+    return ba;
+}
+
+void SymbianAdapter::handleGdbServerCommand(const QByteArray &cmd)
+{
+    // http://sourceware.org/gdb/current/onlinedocs/gdb_34.html
+    if (0) {}
+
+    else if (cmd == "!") {
+        sendGdbServerAck();
+        //sendGdbServerMessage("", "extended mode not enabled");
+        sendGdbServerMessage("OK", "extended mode enabled");
+    }
+
+    else if (cmd.startsWith("?")) {
+        logMessage(msgGdbPacket(QLatin1String("Query halted")));
+        // Indicate the reason the target halted.
+        // The reply is the same as for step and continue.
+        sendGdbServerAck();
+        // The command below will trigger fetching a stack trace while
+        // the process does not seem to be fully functional. Most notably
+        // the PC points to a 0x9..., which is not in "our" range
+        //sendGdbServerMessage("T05library:r;", "target halted (library load)");
+        //sendGdbServerMessage("S05", "target halted (trap)");
+        sendGdbServerMessage("S00", "target halted (trap)");
+        //sendGdbServerMessage("O" + QByteArray("Starting...").toHex());
+    }
+
+    else if (cmd == "c") {
+        logMessage(msgGdbPacket(QLatin1String("Continue")));
+        sendGdbServerAck();
+        QByteArray ba;
+        appendByte(&ba, 0); // options
+        appendInt(&ba, 0); // start address
+        appendInt(&ba, 0); // end address
+        appendInt(&ba, m_session.pid);
+        appendInt(&ba, m_session.tid);
+        sendTrkMessage(0x18, TrkCallback(), ba);
+    }
+
+    else if (cmd.startsWith("C")) {
+        logMessage(msgGdbPacket(QLatin1String("Continue with signal")));
+        // C sig[;addr] Continue with signal sig (hex signal number)
+        //Reply: See section D.3 Stop Reply Packets, for the reply specifications.
+        sendGdbServerAck();
+        bool ok = false;
+        uint signalNumber = cmd.mid(1).toInt(&ok, 16);
+        QByteArray ba;
+        appendInt(&ba, m_session.pid);
+        appendInt(&ba, m_session.tid);
+        sendTrkMessage(0x18, TrkCB(handleSignalContinue), ba, signalNumber); // Continue
+    }
+
+    else if (cmd.startsWith("D")) {
+        sendGdbServerAck();
+        sendGdbServerMessage("OK", "shutting down");
+        qApp->quit();
+    }
+
+    else if (cmd == "g") {
+        logMessage(msgGdbPacket(QLatin1String("Read registers")));
+        // Read general registers.
+        //sendGdbServerMessage("00000000", "read registers");
+        sendGdbServerAck();
+        sendTrkMessage(0x12, TrkCB(handleAndReportReadRegisters),
+            trkReadRegisterMessage());
+    }
+
+    else if (cmd.startsWith("Hc")) {
+        logMessage(msgGdbPacket(QLatin1String("Set thread & continue")));
+        // Set thread for subsequent operations (`m', `M', `g', `G', et.al.).
+        // for step and continue operations
+        //$Hc-1#09
+        sendGdbServerAck();
+        sendGdbServerMessage("OK", "Set current thread for step & continue");
+    }
+
+    else if (cmd.startsWith("Hg")) {
+        logMessage(msgGdbPacket(QLatin1String("Set thread")));
+        // Set thread for subsequent operations (`m', `M', `g', `G', et.al.).
+        // for 'other operations.  0 - any thread
+        //$Hg0#df
+        sendGdbServerAck();
+        m_session.currentThread = cmd.mid(2).toInt(0, 16);
+        sendGdbServerMessage("OK", "Set current thread "
+            + QByteArray::number(m_session.currentThread));
+    }
+
+    else if (cmd == "k") {
+        logMessage(msgGdbPacket(QLatin1String("kill")));
+        // kill
+        sendGdbServerAck();
+        QByteArray ba;
+        appendByte(&ba, 0); // ?
+        appendByte(&ba, 0); // Sub-command: Delete Process
+        appendInt(&ba, m_session.pid);
+        sendTrkMessage(0x41, TrkCallback(), ba, "Delete process"); // Delete Item
+        sendGdbServerMessageAfterTrkResponse("", "process killed");
+    }
+
+    else if (cmd.startsWith("m")) {
+        logMessage(msgGdbPacket(QLatin1String("Read memory")));
+        // m addr,length
+        sendGdbServerAck();
+        uint addr = 0, len = 0;
+        do {
+            const int pos = cmd.indexOf(',');
+            if (pos == -1)
+                break;
+            bool ok;
+            addr = cmd.mid(1, pos - 1).toUInt(&ok, 16);
+            if (!ok)
+                break;
+            len = cmd.mid(pos + 1).toUInt(&ok, 16);
+            if (!ok)
+                break;
+        } while (false);
+        if (len) {
+            readMemory(addr, len);
+        } else {
+            sendGdbServerMessage("E20", "Error " + cmd);
+        }
+    }
+    else if (cmd.startsWith("p")) {
+        logMessage(msgGdbPacket(QLatin1String("read register")));
+        // 0xf == current instruction pointer?
+        //sendGdbServerMessage("0000", "current IP");
+        sendGdbServerAck();
+        #if 0
+          A1 = 0,	 first integer-like argument
+          A4 = 3,	 last integer-like argument
+          AP = 11,
+          IP = 12,
+          SP = 13,	 Contains address of top of stack
+          LR = 14,	 address to return to from a function call
+          PC = 15,	 Contains program counter
+          F0 = 16,	 first floating point register
+          F3 = 19,	 last floating point argument register
+          F7 = 23, 	 last floating point register
+          FPS = 24,	 floating point status register
+          PS = 25,	 Contains processor status
+          WR0,		 WMMX data registers.
+          WR15 = WR0 + 15,
+          WC0,		 WMMX control registers.
+          WCSSF = WC0 + 2,
+          WCASF = WC0 + 3,
+          WC7 = WC0 + 7,
+          WCGR0,		WMMX general purpose registers.
+          WCGR3 = WCGR0 + 3,
+          WCGR7 = WCGR0 + 7,
+          NUM_REGS,
+
+          // Other useful registers.
+          FP = 11,		Frame register in ARM code, if used.
+          THUMB_FP = 7,		Frame register in Thumb code, if used.
+          NUM_ARG_REGS = 4,
+          LAST_ARG = A4,
+          NUM_FP_ARG_REGS = 4,
+          LAST_FP_ARG = F3
+        #endif
+        bool ok = false;
+        const uint registerNumber = cmd.mid(1).toInt(&ok, 16);
+        QByteArray logMsg = "Read Register";
+        if (registerNumber == RegisterPSGdb) {
+            QByteArray ba;
+            appendInt(&ba, m_snapshot.registers[RegisterPSTrk], m_registerEndianness);
+            logMsg += dumpRegister(registerNumber, m_snapshot.registers[RegisterPSTrk]);
+            sendGdbServerMessage(ba.toHex(), logMsg);
+        } else if (registerNumber < RegisterCount) {
+            QByteArray ba;
+            appendInt(&ba, m_snapshot.registers[registerNumber], m_registerEndianness);
+            logMsg += dumpRegister(registerNumber, m_snapshot.registers[registerNumber]);
+            sendGdbServerMessage(ba.toHex(), logMsg);
+        } else {
+            sendGdbServerMessage("0000", "read single unknown register #" + QByteArray::number(registerNumber));
+            //sendGdbServerMessage("E01", "read single unknown register");
+        }
+    }
+
+    else if (cmd == "qAttached") {
+        //$qAttached#8f
+        // 1: attached to an existing process
+        // 0: created a new process
+        sendGdbServerAck();
+        sendGdbServerMessage("0", "new process created");
+        //sendGdbServerMessage("1", "attached to existing process");
+        //sendGdbServerMessage("E01", "new process created");
+    }
+
+    else if (cmd.startsWith("qC")) {
+        logMessage(msgGdbPacket(QLatin1String("query thread id")));
+        // Return the current thread ID
+        //$qC#b4
+        sendGdbServerAck();
+        sendGdbServerMessageAfterTrkResponse("QC@TID@");
+    }
+
+    else if (cmd.startsWith("qSupported")) {
+        //$qSupported#37
+        //$qSupported:multiprocess+#c6
+        //logMessage("Handling 'qSupported'");
+        sendGdbServerAck();
+        if (0)
+            sendGdbServerMessage(QByteArray(), "nothing supported");
+        else
+            sendGdbServerMessage(
+                "PacketSize=7cf;"
+                "QPassSignals+;"
+                "qXfer:libraries:read+;"
+                //"qXfer:auxv:read+;"
+                "qXfer:features:read+");
+    }
+
+    else if (cmd == "qPacketInfo") {
+        // happens with  gdb 6.4.50.20060226-cvs / CodeSourcery
+        // deprecated by qSupported?
+        sendGdbServerAck();
+        sendGdbServerMessage("", "FIXME: nothing?");
+    }
+
+    else if (cmd == "qOffsets") {
+        sendGdbServerAck();
+        sendGdbServerMessageAfterTrkResponse("TextSeg=@CODESEG@;DataSeg=@DATASEG@");
+    }
+
+    else if (cmd == "qSymbol::") {
+        if (m_verbose)
+            logMessage(msgGdbPacket(QLatin1String("notify can handle symbol lookup")));
+        // Notify the target that GDB is prepared to serve symbol lookup requests.
+        sendGdbServerAck();
+        if (1)
+            sendGdbServerMessage("OK", "no further symbols needed");
+        else
+            sendGdbServerMessage("qSymbol:" + QByteArray("_Z7E32Mainv").toHex(), "ask for more");
+    }
+
+    else if (cmd.startsWith("qXfer:features:read:target.xml:")) {
+        //  $qXfer:features:read:target.xml:0,7ca#46...Ack
+        sendGdbServerAck();
+        sendGdbServerMessage("l<target><architecture>symbianelf</architecture></target>");
+    }
+
+    else if (cmd == "QStartNoAckMode") {
+        //$qSupported#37
+        //logMessage("Handling 'QStartNoAckMode'");
+        sendGdbServerAck();
+        sendGdbServerMessage("OK", "ack no-ack mode");
+        m_gdbAckMode = false;
+    }
+
+    else if (cmd.startsWith("QPassSignals")) {
+        // list of signals to pass directly to inferior
+        // $QPassSignals:e;10;14;17;1a;1b;1c;21;24;25;4c;#8f
+        // happens only if "QPassSignals+;" is qSupported
+        sendGdbServerAck();
+        // FIXME: use the parameters
+        sendGdbServerMessage("OK", "passing signals accepted");
+    }
+
+    else if (cmd == "s" || cmd.startsWith("vCont;s")) {
+        logMessage(msgGdbPacket(QLatin1String("Step range")));
+        logMessage("  from " + hexxNumber(m_snapshot.registers[RegisterPC]));
+        sendGdbServerAck();
+        m_running = true;
+        QByteArray ba;
+        appendByte(&ba, 0x01); // options
+        appendInt(&ba, m_snapshot.registers[RegisterPC]); // start address
+        //appendInt(&ba, m_snapshot.registers[RegisterPC] + 4); // end address
+        appendInt(&ba, -1); // end address
+        appendInt(&ba, m_session.pid);
+        appendInt(&ba, m_session.tid);
+        sendTrkMessage(0x19, TrkCB(handleStepRange), ba, "Step range");
+        // FIXME: should be triggered by "real" stop"
+        //sendGdbServerMessageAfterTrkResponse("S05", "target halted");
+    }
+
+    else if (cmd == "vCont?") {
+        // actions supported by the vCont packet
+        sendGdbServerAck();
+        //sendGdbServerMessage("OK"); // we don't support vCont.
+        sendGdbServerMessage("vCont;c;C;s;S");
+    }
+
+    else if (cmd == "vCont;c") {
+        // vCont[;action[:thread-id]]...'
+        sendGdbServerAck();
+        m_running = true;
+        sendTrkMessage(0x18, TrkCallback(), trkContinueMessage(), "CONTINUE");
+    }
+
+    else if (cmd.startsWith("vKill")) {
+        // kill
+        sendGdbServerAck();
+        QByteArray ba;
+        appendByte(&ba, 0); // Sub-command: Delete Process
+        appendInt(&ba, m_session.pid);
+        sendTrkMessage(0x41, TrkCallback(), ba, "Delete process"); // Delete Item
+        sendGdbServerMessageAfterTrkResponse("", "process killed");
+    }
+
+    else if (0 && cmd.startsWith("Z0,")) {
+        // Tell gdb  we don't support software breakpoints
+        sendGdbServerMessage("");
+    }
+
+    else if (cmd.startsWith("Z0,") || cmd.startsWith("Z1,")) {
+        sendGdbServerAck();
+        // Insert breakpoint
+        logMessage(msgGdbPacket(QLatin1String("Insert breakpoint")));
+        // $Z0,786a4ccc,4#99
+        const int pos = cmd.lastIndexOf(',');
+        bool ok = false;
+        const uint addr = cmd.mid(3, pos - 3).toInt(&ok, 16);
+        const uint len = cmd.mid(pos + 1).toInt(&ok, 16);
+        //qDebug() << "ADDR: " << hexNumber(addr) << " LEN: " << len;
+        logMessage(QString::fromLatin1("Inserting breakpoint at 0x%1, %2")
+            .arg(addr, 0, 16).arg(len));
+
+        //---IDE------------------------------------------------------
+        //  Command: 0x1B Set Break
+        //BreakType: 0x82
+        //  Options: 0x00
+        //  Address: 0x78674340 (2020033344)    i.e + 0x00000340
+        //   Length: 0x00000001 (1)
+        //    Count: 0x00000000 (0)
+        //ProcessID: 0x000001b5 (437)
+        // ThreadID: 0xffffffff (-1)
+        // [1B 09 82 00 78 67 43 40 00 00 00 01 00 00 00 00
+        //  00 00 01 B5 FF FF FF FF]
+        const QByteArray ba = trkBreakpointMessage(addr, len, m_session.pid);
+        sendTrkMessage(0x1B, TrkCB(handleAndReportSetBreakpoint), ba, addr);
+        //---TRK------------------------------------------------------
+        //  Command: 0x80 Acknowledge
+        //    Error: 0x00
+        // [80 09 00 00 00 00 0A]
+    }
+
+    else if (cmd.startsWith("z0,") || cmd.startsWith("z1,")) {
+        sendGdbServerAck();
+        // Remove breakpoint
+        logMessage(msgGdbPacket(QLatin1String("Remove breakpoint")));
+        // $z0,786a4ccc,4#99
+        const int pos = cmd.lastIndexOf(',');
+        bool ok = false;
+        const uint addr = cmd.mid(3, pos - 3).toInt(&ok, 16);
+        const uint len = cmd.mid(pos + 1).toInt(&ok, 16);
+        const uint bp = m_session.addressToBP[addr];
+        if (bp == 0) {
+            logMessage(QString::fromLatin1("NO RECORDED BP AT 0x%1, %2")
+                .arg(addr, 0, 16).arg(len));
+        } else {
+            //---IDE------------------------------------------------------
+            //  Command: 0x1C Clear Break
+            // [1C 25 00 00 00 0A 78 6A 43 40]
+            m_session.addressToBP.remove(addr);
+            QByteArray ba;
+            appendByte(&ba, 0x00);
+            appendShort(&ba, bp);
+            appendInt(&ba, addr);
+            sendTrkMessage(0x1C, TrkCB(handleClearBreakpoint), ba, addr);
+        }
+    }
+
+    else if (cmd.startsWith("qPart:") || cmd.startsWith("qXfer:"))  {
+        QByteArray data  = cmd.mid(1 + cmd.indexOf(':'));
+        // "qPart:auxv:read::0,147": Read OS auxiliary data (see info aux)
+        bool handled = false;
+        if (data.startsWith("auxv:read::")) {
+            const int offsetPos = data.lastIndexOf(':') + 1;
+            const int commaPos = data.lastIndexOf(',');
+            if (commaPos != -1) {                
+                bool ok1 = false, ok2 = false;
+                const int offset = data.mid(offsetPos,  commaPos - offsetPos)
+                    .toInt(&ok1, 16);
+                const int length = data.mid(commaPos + 1).toInt(&ok2, 16);
+                if (ok1 && ok2) {
+                    const QString msg = QString::fromLatin1("Read of OS auxilary "
+                        "vector (%1, %2) not implemented.").arg(offset).arg(length);
+                    logMessage(msgGdbPacket(msg), true);
+                    sendGdbServerMessage("E20", msg.toLatin1());
+                    handled = true;
+                }
+            }
+        } // auxv read
+        if (!handled) {
+            const QString msg = QLatin1String("FIXME unknown 'XFER'-request: ")
+                + QString::fromAscii(cmd);
+            logMessage(msgGdbPacket(msg), true);
+            sendGdbServerMessage("E20", msg.toLatin1());
+        }
+    } // qPart/qXfer
+    else {
+        logMessage(msgGdbPacket(QLatin1String("FIXME unknown: ")
+            + QString::fromAscii(cmd)));
+    }
+}
+
+void SymbianAdapter::executeCommand(const QString &msg)
+{
+    if (msg == "EI") {
+        sendGdbMessage("-exec-interrupt");
+    } else if (msg == "C") {
+        sendTrkMessage(0x18, TrkCallback(), trkContinueMessage(), "CONTINUE");
+    } else if (msg == "R") {
+        sendTrkMessage(0x18, TrkCB(handleReadRegisters),
+            trkReadRegisterMessage(), "READ REGS");
+    } else if (msg == "I") {
+        interruptInferior();
+    } else {
+        logMessage("EXECUTING GDB COMMAND " + msg);
+        sendGdbMessage(msg);
+    }
+}
+
+void SymbianAdapter::sendTrkMessage(byte code, TrkCallback callback,
+    const QByteArray &data, const QVariant &cookie)
+{
+    m_trkDevice.sendTrkMessage(code, callback, data, cookie);
+}
+
+void SymbianAdapter::sendTrkAck(byte token)
+{
+    logMessage(QString("SENDING ACKNOWLEDGEMENT FOR TOKEN %1").arg(int(token)));
+    m_trkDevice.sendTrkAck(token);
+}
+
+void SymbianAdapter::handleTrkError(const QString &msg)
+{
+    logMessage("## TRK ERROR: " + msg);
+}
+
+void SymbianAdapter::handleTrkResult(const TrkResult &result)
+{
+    if (result.isDebugOutput) {
+        sendTrkAck(result.token);
+        logMessage(QLatin1String("APPLICATION OUTPUT: ") +
+            QString::fromAscii(result.data));
+        sendGdbServerMessage("O" + result.data.toHex());
+        return;
+    }
+    logMessage("READ TRK " + result.toString());
+    QByteArray prefix = "READ BUF:                                       ";
+    QByteArray str = result.toString().toUtf8();
+    switch (result.code) {
+        case 0x80: // ACK
+            break;
+        case 0xff: { // NAK. This mostly means transmission error, not command failed.
+            QString logMsg;
+            QTextStream(&logMsg) << prefix << "NAK: for token=" << result.token
+                << " ERROR: " << errorMessage(result.data.at(0)) << ' ' << str;
+            logMessage(logMsg, true);
+            break;
+        }
+        case 0x90: { // Notified Stopped
+            // 90 01   78 6a 40 40   00 00 07 23   00 00 07 24  00 00
+            const char *data = result.data.data();
+            const uint addr = extractInt(data);
+            const uint pid = extractInt(data + 4);
+            const uint tid = extractInt(data + 8);
+            logMessage(prefix + QString::fromLatin1("NOTE: PID %1/TID %2 "
+                "STOPPED at 0x%3").arg(pid).arg(tid).arg(addr, 0, 16));
+            sendTrkAck(result.token);
+            if (addr) {
+                // Todo: Do not send off GdbMessages if a synced gdb
+                // query is pending, queue instead
+                if (m_running) {
+                    m_running = false;
+                    sendGdbServerMessage("S05", "Target stopped");
+                }
+            } else {
+                logMessage(QLatin1String("Ignoring stop at 0"));
+            }
+            break;
+        }
+        case 0x91: { // Notify Exception (obsolete)
+            logMessage(prefix + "NOTE: EXCEPTION  " + str);
+            sendTrkAck(result.token);
+            break;
+        }
+        case 0x92: { //
+            logMessage(prefix + "NOTE: INTERNAL ERROR: " + str);
+            sendTrkAck(result.token);
+            break;
+        }
+
+        // target->host OS notification
+        case 0xa0: { // Notify Created
+            const char *data = result.data.data();
+            const byte error = result.data.at(0);
+            // type: 1 byte; for dll item, this value is 2.
+            const byte type = result.data.at(1);
+            const uint pid = extractInt(data + 2);
+            const uint tid = extractInt(data + 6);
+            const uint codeseg = extractInt(data + 10);
+            const uint dataseg = extractInt(data + 14);
+            const uint len = extractShort(data + 18);
+            const QByteArray name = result.data.mid(20, len); // library name
+            m_session.modules += QString::fromAscii(name);
+            QString logMsg;
+            QTextStream str(&logMsg);
+            str << prefix << " NOTE: LIBRARY LOAD: token=" << result.token;
+            if (error)
+                str << " ERROR: " << int(error);
+            str << " TYPE: " << int(type) << " PID: " << pid << " TID:   " <<  tid;
+            str << " CODE: " << hexxNumber(codeseg);
+            str << " DATA: " << hexxNumber(dataseg);
+            str << " NAME: '" << name << '\'';
+            logMessage(logMsg);
+            // This lets gdb trigger a register update etc
+            //sendGdbServerMessage("T05library:r;");
+            sendTrkMessage(0x18, TrkCallback(), trkContinueMessage(), "CONTINUE");
+            break;
+        }
+        case 0xa1: { // NotifyDeleted
+            const ushort itemType = extractByte(result.data.data() + 1);
+            const ushort len = result.data.size() > 12
+                ? extractShort(result.data.data() + 10) : ushort(0);
+            const QString name = len
+                ? QString::fromAscii(result.data.mid(12, len)) : QString();
+            if (!name.isEmpty())
+                m_session.modules.removeAll(name);
+            logMessage(QString::fromLatin1("%1 %2 UNLOAD: %3")
+                .arg(QString::fromAscii(prefix))
+                .arg(itemType ? QLatin1String("LIB") : QLatin1String("PROCESS"))
+                .arg(name));
+            sendTrkAck(result.token);
+            if (itemType == 0) {
+                sendGdbServerMessage("W00", "Process exited");
+                //sendTrkMessage(0x02, TrkCB(handleDisconnect));
+            }
+            break;
+        }
+        case 0xa2: { // NotifyProcessorStarted
+            logMessage(prefix + "NOTE: PROCESSOR STARTED: " + str);
+            sendTrkAck(result.token);
+            break;
+        }
+        case 0xa6: { // NotifyProcessorStandby
+            logMessage(prefix + "NOTE: PROCESSOR STANDBY: " + str);
+            sendTrkAck(result.token);
+            break;
+        }
+        case 0xa7: { // NotifyProcessorReset
+            logMessage(prefix + "NOTE: PROCESSOR RESET: " + str);
+            sendTrkAck(result.token);
+            break;
+        }
+        default: {
+            logMessage(prefix + "INVALID: " + str);
+            break;
+        }
+    }
+}
+
+void SymbianAdapter::handleCpuType(const TrkResult &result)
+{
+    //---TRK------------------------------------------------------
+    //  Command: 0x80 Acknowledge
+    //    Error: 0x00
+    // [80 03 00  04 00 00 04 00 00 00]
+    m_session.cpuMajor = result.data[1];
+    m_session.cpuMinor = result.data[2];
+    m_session.bigEndian = result.data[3];
+    m_session.defaultTypeSize = result.data[4];
+    m_session.fpTypeSize = result.data[5];
+    m_session.extended1TypeSize = result.data[6];
+    //m_session.extended2TypeSize = result.data[6];
+    QString logMsg;
+    QTextStream(&logMsg) << "HANDLE CPU TYPE: CPU=" << m_session.cpuMajor << '.'
+        << m_session.cpuMinor << " bigEndian=" << m_session.bigEndian
+        << " defaultTypeSize=" << m_session.defaultTypeSize
+        << " fpTypeSize=" << m_session.fpTypeSize
+        << " extended1TypeSize=" <<  m_session.extended1TypeSize;
+    logMessage(logMsg);
+}
+
+void SymbianAdapter::handleSetTrkBreakpoint(const TrkResult &result)
+{
+    //---TRK------------------------------------------------------
+    //  Command: 0x80 Acknowledge
+    //    Error: 0x00
+    // [80 09 00 00 00 00 0A]
+    const uint bpnr = extractInt(result.data.data());
+    logMessage("SET BREAKPOINT " + hexxNumber(bpnr)
+        + stringFromArray(result.data.data()));
+}
+
+void SymbianAdapter::handleCreateProcess(const TrkResult &result)
+{
+    //  40 00 00]
+    //logMessage("       RESULT: " + result.toString());
+    // [80 08 00   00 00 01 B5   00 00 01 B6   78 67 40 00   00 40 00 00]
+    const char *data = result.data.data();
+    m_session.pid = extractInt(data + 1);
+    m_session.tid = extractInt(data + 5);
+    m_session.codeseg = extractInt(data + 9);
+    m_session.dataseg = extractInt(data + 13);
+
+    logMessage("PID: " + hexxNumber(m_session.pid));
+    logMessage("TID: " + hexxNumber(m_session.tid));
+    logMessage("COD: " + hexxNumber(m_session.codeseg));
+    logMessage("DAT: " + hexxNumber(m_session.dataseg));
+
+    QByteArray ba;
+    appendInt(&ba, m_session.pid);
+    appendInt(&ba, m_session.tid);
+
+    startGdb();
+
+
+#if 0
+    //---IDE------------------------------------------------------
+    //  Command: 0x42 Read Info
+    //          [42 0C 00 06 00 00 00 00 00 14 50 6F 6C 79 6D 6F
+    //  72 70 68 69 63 44 4C 4C 32 2E 64 6C 6C 00]
+    sendTrkMessage(0x42, TrkCB(handleReadInfo),
+        "00 06 00 00 00 00 00 14 50 6F 6C 79 6D 6F "
+        "72 70 68 69 63 44 4C 4C 32 2E 64 6C 6C 00");
+    //sendTrkMessage(0x42, TrkCB(handleReadInfo),
+    //        "00 01 00 00 00 00");
+    //---TRK------------------------------------------------------
+    //  Command: 0x80 Acknowledge
+    //    Error: 0x20 Unspecified general OS-related error
+    // [80 0C 20]
+
+
+    //---IDE------------------------------------------------------
+    //  Command: 0x42 Read Info
+    // [42 0D 00 06 00 00 00 00 00 14 50 6F 6C 79 6D 6F
+    //  72 70 68 69 63 44 4C 4C 31 2E 64 6C 6C 00]
+    sendTrkMessage(0x42, TrkCB(handleReadInfo),
+        "00 06 00 00 00 00 00 14 50 6F 6C 79 6D 6F "
+        "72 70 68 69 63 44 4C 4C 31 2E 64 6C 6C 00");
+    //---TRK------------------------------------------------------
+    //  Command: 0x80 Acknowledge
+    //    Error: 0x20 Unspecified general OS-related error
+    // [80 0D 20]
+#endif
+
+    //sendTrkMessage(0x18, TrkCB(handleStop),
+    //    "01 " + formatInt(m_session.pid) + formatInt(m_session.tid));
+}
+
+void SymbianAdapter::handleReadRegisters(const TrkResult &result)
+{
+    logMessage("       RESULT: " + result.toString());
+    // [80 0B 00   00 00 00 00   C9 24 FF BC   00 00 00 00   00
+    //  60 00 00   00 00 00 00   78 67 79 70   00 00 00 00   00...]
+    if (result.errorCode()) {
+        logMessage("ERROR: " + result.errorString());
+        return;
+    }
+    const char *data = result.data.data() + 1; // Skip ok byte
+    for (int i = 0; i < RegisterCount; ++i)
+        m_snapshot.registers[i] = extractInt(data + 4 * i);
+} 
+
+void SymbianAdapter::handleAndReportReadRegisters(const TrkResult &result)
+{
+    handleReadRegisters(result);
+    QByteArray ba;
+    for (int i = 0; i < 16; ++i) {
+        const uint reg = m_registerEndianness == LittleEndian
+            ? swapEndian(m_snapshot.registers[i]) : m_snapshot.registers[i];
+        ba += hexNumber(reg, 8);
+    }
+    QByteArray logMsg = "REGISTER CONTENTS: ";
+    if (m_verbose > 1) {
+        for (int i = 0; i < RegisterCount; ++i) {
+            logMsg += dumpRegister(i, m_snapshot.registers[i]);
+            logMsg += ' ';
+        }
+    }
+    sendGdbServerMessage(ba, logMsg);
+}
+
+static inline QString msgMemoryReadError(int code, uint addr, uint len = 0)
+{
+    const QString lenS = len ? QString::number(len) : QLatin1String("<unknown>");
+    return QString::fromLatin1("Memory read error %1 at: 0x%2 %3")
+        .arg(code).arg(addr, 0 ,16).arg(lenS);
+}
+
+void SymbianAdapter::handleReadMemoryBuffered(const TrkResult &result)
+{
+    if (extractShort(result.data.data() + 1) + 3 != result.data.size())
+        logMessage("\n BAD MEMORY RESULT: " + result.data.toHex() + "\n");
+    const uint blockaddr = result.cookie.toUInt();
+    if (const int errorCode = result.errorCode()) {
+        logMessage(msgMemoryReadError(errorCode, blockaddr));
+        return;
+    }
+    const QByteArray ba = result.data.mid(3);
+    m_snapshot.memory.insert(blockaddr, ba);
+}
+
+// Format log message for memory access with some smartness about registers
+QByteArray SymbianAdapter::memoryReadLogMessage(uint addr, uint len, const QByteArray &ba) const
+{
+    QByteArray logMsg = "memory contents";
+    if (m_verbose > 1) {
+        logMsg += " addr: " + hexxNumber(addr);
+        // indicate dereferencing of registers
+        if (len == 4) {
+            if (addr == m_snapshot.registers[RegisterPC]) {
+                logMsg += "[PC]";
+            } else if (addr == m_snapshot.registers[RegisterPSTrk]) {
+                logMsg += "[PSTrk]";
+            } else if (addr == m_snapshot.registers[RegisterSP]) {
+                logMsg += "[SP]";
+            } else if (addr == m_snapshot.registers[RegisterLR]) {
+                logMsg += "[LR]";
+            } else if (addr > m_snapshot.registers[RegisterSP] &&
+                    (addr - m_snapshot.registers[RegisterSP]) < 10240) {
+                logMsg += "[SP+"; // Stack area ...stack seems to be top-down
+                logMsg += QByteArray::number(addr - m_snapshot.registers[RegisterSP]);
+                logMsg += ']';
+            }
+        }
+        logMsg += " length ";
+        logMsg += QByteArray::number(len);
+        logMsg += " :";
+        logMsg += stringFromArray(ba, 16).toAscii();
+    }
+    return logMsg;
+}
+
+void SymbianAdapter::reportReadMemoryBuffered(const TrkResult &result)
+{
+    const qulonglong cookie = result.cookie.toULongLong();
+    const uint addr = cookie >> 32;
+    const uint len = uint(cookie);
+
+    // Gdb accepts less memory according to documentation.
+    // Send E on complete failure.
+    QByteArray ba;
+    uint blockaddr = (addr / MemoryChunkSize) * MemoryChunkSize;
+    for (; blockaddr < addr + len; blockaddr += MemoryChunkSize) {
+        const Snapshot::Memory::const_iterator it = m_snapshot.memory.constFind(blockaddr);
+        if (it == m_snapshot.memory.constEnd())
+            break;
+        ba.append(it.value());
+    }
+    const int previousChunkOverlap = addr % MemoryChunkSize;
+    if (previousChunkOverlap != 0 && ba.size() > previousChunkOverlap)
+        ba.remove(0, previousChunkOverlap);
+    if (ba.size() > int(len))
+        ba.truncate(len);
+
+    if (ba.isEmpty()) {
+        ba = "E20";
+        sendGdbServerMessage(ba, msgMemoryReadError(32, addr, len).toLatin1());
+    } else {
+        sendGdbServerMessage(ba.toHex(), memoryReadLogMessage(addr, len, ba));
+    }
+}
+
+void SymbianAdapter::handleReadMemoryUnbuffered(const TrkResult &result)
+{
+    //logMessage("UNBUFFERED MEMORY READ: " + stringFromArray(result.data));
+    const uint blockaddr = result.cookie.toUInt();
+    if (extractShort(result.data.data() + 1) + 3 != result.data.size())
+        logMessage("\n BAD MEMORY RESULT: " + result.data.toHex() + "\n");
+    if (const int errorCode = result.errorCode()) {
+        const QByteArray ba = "E20";
+        sendGdbServerMessage(ba, msgMemoryReadError(32, blockaddr).toLatin1());
+    } else {
+        const QByteArray ba = result.data.mid(3);
+        sendGdbServerMessage(ba.toHex(), memoryReadLogMessage(blockaddr, ba.size(), ba));
+    }
+}
+
+void SymbianAdapter::handleStepRange(const TrkResult &result)
+{
+    // [80 0f 00]
+    if (result.errorCode()) {
+        logMessage("ERROR: " + result.errorString());
+        return;
+    }
+    logMessage("STEPPING FINISHED ");
+    //sendGdbServerMessage("S05", "Stepping finished");
+}
+
+void SymbianAdapter::handleAndReportSetBreakpoint(const TrkResult &result)
+{
+    //---TRK------------------------------------------------------
+    //  Command: 0x80 Acknowledge
+    //    Error: 0x00
+    // [80 09 00 00 00 00 0A]
+    uint bpnr = extractByte(result.data.data());
+    uint addr = result.cookie.toUInt();
+    m_session.addressToBP[addr] = bpnr;
+    logMessage("SET BREAKPOINT " + hexxNumber(bpnr) + " "
+         + stringFromArray(result.data.data()));
+    sendGdbServerMessage("OK");
+    //sendGdbServerMessage("OK");
+}
+
+void SymbianAdapter::handleClearBreakpoint(const TrkResult &result)
+{
+    logMessage("CLEAR BREAKPOINT ");
+    if (result.errorCode()) {
+        logMessage("ERROR: " + result.errorString());
+        //return;
+    } 
+    //---TRK------------------------------------------------------
+    //  Command: 0x80 Acknowledge
+    //    Error: 0x00
+    // [80 09 00 00 00 00 0A]
+    // FIXME:
+    sendGdbServerMessage("OK");
+}
+
+void SymbianAdapter::handleSignalContinue(const TrkResult &result)
+{
+    int signalNumber = result.cookie.toInt();
+    logMessage("   HANDLE SIGNAL CONTINUE: " + stringFromArray(result.data));
+    logMessage("NUMBER" + QString::number(signalNumber));
+    sendGdbServerMessage("O" + QByteArray("Console output").toHex());
+    sendGdbServerMessage("W81"); // "Process exited with result 1
+}
+
+void SymbianAdapter::handleSupportMask(const TrkResult &result)
+{
+    const char *data = result.data.data();
+    QByteArray str;
+    for (int i = 0; i < 32; ++i) {
+        //str.append("  [" + formatByte(data[i]) + "]: ");
+        for (int j = 0; j < 8; ++j)
+        if (data[i] & (1 << j))
+            str.append(QByteArray::number(i * 8 + j, 16));
+    }
+    logMessage("SUPPORTED: " + str);
+ }
+
+void SymbianAdapter::handleTrkVersions(const TrkResult &result)
+{
+    QString logMsg;
+    QTextStream str(&logMsg);
+    str << "Versions: ";
+    if (result.data.size() >= 5) {
+        str << "Trk version " << int(result.data.at(1)) << '.'
+            << int(result.data.at(2))
+            << ", Protocol version " << int(result.data.at(3))
+             << '.' << int(result.data.at(4));
+    }
+    logMessage(logMsg);
+}
+
+void SymbianAdapter::handleDisconnect(const TrkResult & /*result*/)
+{
+    logMessage(QLatin1String("Trk disconnected"), true);
+}
+
+void SymbianAdapter::readMemory(uint addr, uint len)
+{
+    Q_ASSERT(len < (2 << 16));
+
+    // We try to get medium-sized chunks of data from the device
+    if (m_verbose > 2)
+        logMessage(QString::fromLatin1("readMemory %1 bytes from 0x%2 blocksize=%3")
+            .arg(len).arg(addr, 0, 16).arg(MemoryChunkSize));
+
+    if (m_bufferedMemoryRead) {
+        uint blockaddr = (addr / MemoryChunkSize) * MemoryChunkSize;
+        for (; blockaddr < addr + len; blockaddr += MemoryChunkSize) {
+            if (!m_snapshot.memory.contains(blockaddr)) {
+                if (m_verbose)
+                    logMessage(QString::fromLatin1("Requesting buffered "
+                        "memory %1 bytes from 0x%2")
+                    .arg(MemoryChunkSize).arg(blockaddr, 0, 16));
+                sendTrkMessage(0x10, TrkCB(handleReadMemoryBuffered),
+                    trkReadMemoryMessage(blockaddr, MemoryChunkSize),
+                    QVariant(blockaddr));
+            }
+        }
+        const qulonglong cookie = (qulonglong(addr) << 32) + len;
+        sendTrkMessage(TRK_WRITE_QUEUE_NOOP_CODE, TrkCB(reportReadMemoryBuffered),
+            QByteArray(), cookie);
+    } else {
+        if (m_verbose)
+            logMessage(QString::fromLatin1("Requesting unbuffered memory %1 "
+                "bytes from 0x%2").arg(len).arg(addr, 0, 16));
+        sendTrkMessage(0x10, TrkCB(handleReadMemoryUnbuffered),
+           trkReadMemoryMessage(addr, len), QVariant(addr));
+    }
+}
+
+void SymbianAdapter::interruptInferior()
+{
+    QByteArray ba;
+    // stop the thread (2) or the process (1) or the whole system (0)
+    // We choose 2, as 1 does not seem to work.
+    appendByte(&ba, 2);
+    appendInt(&ba, m_session.pid);
+    appendInt(&ba, m_session.tid); // threadID: 4 bytes Variable number of bytes.
+    sendTrkMessage(0x1a, TrkCallback(), ba, "Interrupting...");
+}
+
+void SymbianAdapter::connectProcess(QProcess *proc)
+{
+    connect(proc, SIGNAL(error(QProcess::ProcessError)),
+        this, SLOT(handleProcError(QProcess::ProcessError)));
+    connect(proc, SIGNAL(finished(int, QProcess::ExitStatus)),
+        this, SLOT(handleProcFinished(int, QProcess::ExitStatus)));
+    connect(proc, SIGNAL(started()),
+        this, SLOT(handleProcStarted()));
+    connect(proc, SIGNAL(stateChanged(QProcess::ProcessState)),
+        this, SLOT(handleProcStateChanged(QProcess::ProcessState)));
+}
+
+void SymbianAdapter::sendOutput(QObject *sender, const QString &data)
+{
+    if (sender)
+        emit output(sender->objectName() + " : ", data);
+    else
+        emit output(QString(), data);
+}
+
+void SymbianAdapter::handleProcError(QProcess::ProcessError error)
+{
+    sendOutput(sender(), QString("Process Error %1").arg(error));
+}
+
+void SymbianAdapter::handleProcFinished(int exitCode, QProcess::ExitStatus exitStatus)
+{
+    sendOutput(sender(),
+        QString("ProcessFinished %1 %2").arg(exitCode).arg(exitStatus));
+}
+
+void SymbianAdapter::handleProcStarted()
+{
+    sendOutput(sender(), QString("Process Started"));
+}
+
+void SymbianAdapter::handleProcStateChanged(QProcess::ProcessState newState)
+{
+    sendOutput(sender(), QString("Process State %1").arg(newState));
+}
+
+void SymbianAdapter::run()
+{
+    sendOutput("### Starting SymbianAdapter");
+    m_rfcommProc.start("rfcomm listen " + m_rfcommDevice + " 1");
+    m_rfcommProc.waitForStarted();
+
+    connect(&m_trkDevice, SIGNAL(messageReceived(trk::TrkResult)),
+        this, SLOT(handleTrkResult(trk::TrkResult)));
+    connect(&m_trkDevice, SIGNAL(error(QString)),
+        this, SLOT(handleTrkError(QString)));
+
+    startInferior();
+}
+
+void SymbianAdapter::startGdb()
+{
+    if (!m_gdbServer.listen(QHostAddress(gdbServerIP()), gdbServerPort())) {
+        logMessage(QString("Unable to start the gdb server at %1: %2.")
+            .arg(m_gdbServerName).arg(m_gdbServer.errorString()), true);
+        QCoreApplication::exit(5);
+        return;
+    }
+
+    logMessage(QString("Gdb server running on %1.\nRegister endianness: %3.")
+        .arg(m_gdbServerName).arg(m_registerEndianness), true);
+
+    connect(&m_gdbServer, SIGNAL(newConnection()),
+        this, SLOT(handleGdbConnection()));
+
+    logMessage("STARTING GDB");
+    QStringList gdbArgs;
+    gdbArgs.append("--nx"); // Do not read .gdbinit file
+    gdbArgs.append("-i");
+    gdbArgs.append("mi");
+    m_gdbProc.start(QDir::currentPath() + "/cs-gdb", gdbArgs);
+    m_gdbProc.waitForStarted();
+
+    sendGdbMessage("set confirm off"); // confirm potentially dangerous operations?
+    sendGdbMessage("set endian little");
+    sendGdbMessage("set remotebreak on");
+    sendGdbMessage("set breakpoint pending on");
+    sendGdbMessage("set trust-readonly-sections on");
+    //sendGdbMessage("mem 0 ~0ll rw 8 cache");
+
+    // FIXME: "remote noack" does not seem to be supported on cs-gdb?
+    //sendGdbMessage("set remote noack-packet");
+
+    // FIXME: creates a lot of noise a la  '&"putpkt: Junk: Ack " &'
+    // even thouhg the communication seems sane
+    //sendGdbMessage("set debug remote 1"); // creates l
+
+    //sendGdbMessage("target remote " + m_gdbServerName);
+//    sendGdbMessage("target extended-remote " + m_gdbServerName);
+    //sendGdbMessage("target extended-async " + m_gdbServerName);
+    //sendGdbMessage("set remotecache ...") // Set cache use for remote targets 
+    //sendGdbMessage("file filebrowseapp.sym");
+//    sendGdbMessage("add-symbol-file filebrowseapp.sym " + m_baseAddress);
+//    sendGdbMessage("symbol-file filebrowseapp.sym");
+//    sendGdbMessage("print E32Main");
+//    sendGdbMessage("break E32Main");
+    //sendGdbMessage("continue");
+    //sendGdbMessage("info files");
+    //sendGdbMessage("file filebrowseapp.sym -readnow");
+
+    sendGdbMessage("add-symbol-file filebrowseapp.sym "
+        + hexxNumber(m_session.codeseg));
+    sendGdbMessage("symbol-file filebrowseapp.sym");
+
+    // -symbol-info-address not implemented in cs-gdb 6.4-6.8 (at least)
+    sendGdbMessage("info address E32Main",
+        GdbCB(handleInfoMainAddress)); 
+    sendGdbMessage("info address CFileBrowseAppUi::HandleCommandL",
+        GdbCB(handleInfoMainAddress)); 
+        
+#if 1
+    // FIXME: Gdb based version. That's the goal
+    //sendGdbMessage("break E32Main");
+    //sendGdbMessage("continue");
+    //sendTrkMessage(0x18, TrkCB(handleContinueAfterCreateProcess), 
+    // trkContinueMessage(), "CONTINUE");
+#else
+    // Directly talk to TRK. Works for now...
+    sendGdbMessage("break E32Main");
+    sendGdbMessage("break filebrowseappui.cpp:39");
+   //         sendTrkMessage(0x18, TrkCallback(), trkContinueMessage(), "CONTINUE");
+#endif
+}
+
+void SymbianAdapter::sendGdbMessage(const QString &msg, GdbCallback callback,
+    const QVariant &cookie)
+{
+    static int token = 0;
+    ++token;
+    GdbCommand data;
+    data.command = msg;
+    data.callback = callback;
+    data.cookie = cookie;
+    m_gdbCookieForToken[token] = data;
+    logMessage(QString("<- GDB: %1 %2").arg(token).arg(msg));
+    m_gdbProc.write(QString("%1%2\n").arg(token).arg(msg).toLatin1());
+}
+
+void SymbianAdapter::handleGdbReadyReadStandardError()
+{
+    QByteArray ba = qobject_cast<QProcess *>(sender())->readAllStandardError();
+    sendOutput(sender(), QString("stderr: %1").arg(QString::fromLatin1(ba)));
+}
+
+void SymbianAdapter::handleGdbReadyReadStandardOutput()
+{
+    QByteArray ba = qobject_cast<QProcess *>(sender())->readAllStandardOutput();
+    QString str = QString::fromLatin1(ba);
+    // FIXME: fragile. merge with gdbengine logic
+#if 0
+    QRegExp re(QString(".*([0-9]+)[^]done.*"));
+    int pos = re.indexIn(str);
+    if (pos == -1) {
+        logMessage(QString("\n-> GDB: %1 %**% %2 %**%\n").arg(str).arg(pos));
+        return;
+    }
+    int token = re.cap(1).toInt();
+    logMessage(QString("\n-> GDB: %1 %2##\n").arg(token).arg(QString::fromLatin1(ba)));
+    if (!token)
+        return;
+    GdbCommand cmd = m_gdbCookieForToken.take(token);
+    logMessage("FOUND CALLBACK FOR " + cmd.command);
+    GdbResult result;
+    result.data = ba;
+    if (!cmd.callback.isNull())
+        cmd.callback(result);
+#else
+    bool ok;
+    QRegExp re(QString("Symbol .._Z7E32Mainv.. is a function at address 0x(.*)\\."));
+    if (re.indexIn(str) != -1) {
+        logMessage(QString("-> GDB MAIN BREAKPOINT: %1").arg(re.cap(1)));
+        uint addr = re.cap(1).toInt(&ok, 16);
+        sendTrkMessage(0x1B, TrkCallback(), trkBreakpointMessage(addr, 1));
+        return;
+    }
+    QRegExp re1(QString("Symbol .._ZN16CFileBrowseAppUi14HandleCommandLEi.. is a function at address 0x(.*)\\."));
+    if (re1.indexIn(str) != -1) {
+        logMessage(QString("-> GDB USER BREAKPOINT: %1").arg(re1.cap(1)));
+        uint addr = re1.cap(1).toInt(&ok, 16);
+        sendTrkMessage(0x1B, TrkCallback(), trkBreakpointMessage(addr, 1));
+
+        sendTrkMessage(0x18, TrkCallback(), trkContinueMessage(), "CONTINUE");
+        sendGdbMessage("target remote " + m_gdbServerName);
+        return;
+    }
+    logMessage(QString("-> GDB: %1").arg(str));
+#endif
+}
+
+void SymbianAdapter::handleInfoMainAddress(const GdbResult &result)
+{
+    Q_UNUSED(result);
+}
+
+void SymbianAdapter::handleSetTrkMainBreakpoint(const TrkResult &result)
+{
+    Q_UNUSED(result);
+/*
+    //---TRK------------------------------------------------------
+    // [80 09 00 00 00 00 0A]
+    const uint bpnr = extractInt(result.data.data());
+    logMessage("SET MAIN BREAKPOINT " + hexxNumber(bpnr)
+        + stringFromArray(result.data.data()));
+*/
+}
+
+void SymbianAdapter::handleInfoAddress(const GdbResult &result)
+{
+    Q_UNUSED(result);
+    // FIXME
+}
+
+void SymbianAdapter::handleRfcommReadyReadStandardError()
+{
+    QByteArray ba = qobject_cast<QProcess *>(sender())->readAllStandardError();
+    sendOutput(sender(), QString("stderr: %1").arg(QString::fromLatin1(ba)));
+}
+
+void SymbianAdapter::handleRfcommReadyReadStandardOutput()
+{
+    QByteArray ba = qobject_cast<QProcess *>(sender())->readAllStandardOutput();
+    sendOutput(sender(), QString("stdout: %1").arg(QString::fromLatin1(ba)));
+}
+
+//
+// GdbProcessBase
+//
+
+void SymbianAdapter::start(const QString &program, const QStringList &args,
+    QIODevice::OpenMode mode)
+{
+    //m_gdbProc.start(program, args, mode);
+}
+
+void SymbianAdapter::kill()
+{
+    //m_gdbProc.kill();
+}
+
+void SymbianAdapter::terminate()
+{
+    //m_gdbProc.terminate();
+}
+
+bool SymbianAdapter::waitForStarted(int msecs)
+{
+    //return m_gdbProc.waitForStarted(msecs);
+    return true;
+}
+
+bool SymbianAdapter::waitForFinished(int msecs)
+{
+    //return m_gdbProc.waitForFinished(msecs);
+    return true;
+}
+
+QProcess::ProcessState SymbianAdapter::state() const
+{
+    return m_gdbProc.state();
+}
+
+QString SymbianAdapter::errorString() const
+{
+    return m_gdbProc.errorString();
+}
+
+QByteArray SymbianAdapter::readAllStandardError()
+{
+    return m_gdbProc.readAllStandardError();
+}
+
+QByteArray SymbianAdapter::readAllStandardOutput()
+{
+    return m_gdbProc.readAllStandardOutput();
+}
+
+qint64 SymbianAdapter::write(const char *data)
+{
+    return m_gdbProc.write(data);
+}
+
+void SymbianAdapter::setWorkingDirectory(const QString &dir)
+{
+    m_gdbProc.setWorkingDirectory(dir);
+}
+
+void SymbianAdapter::setEnvironment(const QStringList &env)
+{
+    m_gdbProc.setEnvironment(env);
+}
+
+} // namespace Internal
+} // namespace Debugger
diff --git a/src/plugins/debugger/symbian/symbianadapter.h b/src/plugins/debugger/symbian/symbianadapter.h
new file mode 100644
index 0000000000000000000000000000000000000000..45c5b762c04818885c88d1c6a0ae6d0f0cb56c01
--- /dev/null
+++ b/src/plugins/debugger/symbian/symbianadapter.h
@@ -0,0 +1,247 @@
+/**************************************************************************
+**
+** 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.
+**
+**************************************************************************/
+
+#ifndef DEBUGGER_SYMBIANADAPTER_H
+#define DEBUGGER_SYMBIANADAPTER_H
+
+#include "trkutils.h"
+#include "trkclient.h"
+#include "../gdb/gdbprocessbase.h"
+
+#include <QtCore/QDebug>
+#include <QtCore/QDir>
+#include <QtCore/QFile>
+#include <QtCore/QHash>
+#include <QtCore/QPointer>
+#include <QtCore/QProcess>
+#include <QtCore/QQueue>
+#include <QtCore/QString>
+#include <QtCore/QStringList>
+#include <QtCore/QTextStream>
+#include <QtCore/QTimer>
+
+#include <QtGui/QAction>
+#include <QtGui/QApplication>
+#include <QtGui/QMainWindow>
+#include <QtGui/QKeyEvent>
+#include <QtGui/QTextBlock>
+#include <QtGui/QTextEdit>
+#include <QtGui/QToolBar>
+
+#include <QtNetwork/QTcpServer>
+#include <QtNetwork/QTcpSocket>
+#include <QtNetwork/QLocalServer>
+#include <QtNetwork/QLocalSocket>
+
+namespace Debugger {
+namespace Internal {
+
+struct GdbResult
+{
+    QByteArray data;
+};
+
+///////////////////////////////////////////////////////////////////////
+//
+// SymbianAdapter
+//
+///////////////////////////////////////////////////////////////////////
+
+class SymbianAdapter : public GdbProcessBase
+{
+    Q_OBJECT
+
+public:
+    typedef trk::TrkResult TrkResult;
+    typedef trk::TrkFunctor1<const TrkResult &> TrkCallback;
+    typedef trk::TrkFunctor1<const GdbResult &> GdbCallback;
+
+    SymbianAdapter();
+    ~SymbianAdapter();
+    void setGdbServerName(const QString &name);
+    QString gdbServerIP() const;
+    uint gdbServerPort() const;
+    void setVerbose(int verbose) { m_verbose = verbose; }
+    void setSerialFrame(bool b) { m_serialFrame = b; }
+    void setBufferedMemoryRead(bool b) { m_bufferedMemoryRead = b; }
+
+public slots:
+    void startInferior();
+
+signals:
+    void output(const QString &senderName, const QString &data);
+
+private slots:
+    void handleProcError(QProcess::ProcessError error);
+    void handleProcFinished(int exitCode, QProcess::ExitStatus exitStatus);
+    void handleProcStarted();
+    void handleProcStateChanged(QProcess::ProcessState newState);
+    void run();
+    void startGdb();
+
+private:
+    friend class RunnerGui;
+    void connectProcess(QProcess *proc);
+    void sendOutput(QObject *sender, const QString &data);
+    void sendOutput(const QString &data) { sendOutput(0, data); }
+
+    QString m_rfcommDevice;  // /dev/rfcomm0
+    QString m_gdbServerName; // 127.0.0.1:(2222+uid)
+
+    QProcess m_gdbProc;
+    QProcess m_rfcommProc;
+    bool m_running;
+
+public:
+    //
+    // Implementation of GdbProcessBase
+    //
+    void start(const QString &program, const QStringList &args,
+        QIODevice::OpenMode mode = QIODevice::ReadWrite);
+    void kill();
+    void terminate();
+    bool waitForStarted(int msecs = 30000);
+    bool waitForFinished(int msecs = 30000);
+    QProcess::ProcessState state() const;
+    QString errorString() const;
+    QByteArray readAllStandardError();
+    QByteArray readAllStandardOutput();
+    qint64 write(const char *data);
+    void setWorkingDirectory(const QString &dir);
+    void setEnvironment(const QStringList &env);
+
+    //
+    // TRK
+    //
+    void sendTrkMessage(byte code,
+        TrkCallback callback = TrkCallback(),
+        const QByteArray &data = QByteArray(),
+        const QVariant &cookie = QVariant());
+    Q_SLOT void handleTrkResult(const trk::TrkResult &data);
+    Q_SLOT void handleTrkError(const QString &msg);
+
+    // convenience messages
+    void sendTrkAck(byte token);
+
+    void handleCpuType(const TrkResult &result);
+    void handleCreateProcess(const TrkResult &result);
+    void handleClearBreakpoint(const TrkResult &result);
+    void handleSignalContinue(const TrkResult &result);
+    void handleStop(const TrkResult &result);
+    void handleSupportMask(const TrkResult &result);
+    void handleTrkVersions(const TrkResult &result);
+    void handleDisconnect(const TrkResult &result);
+
+    void handleAndReportCreateProcess(const TrkResult &result);
+    void handleAndReportReadRegisters(const TrkResult &result);
+    QByteArray memoryReadLogMessage(uint addr, uint len, const QByteArray &ba) const;
+    QByteArray trkContinueMessage();
+    QByteArray trkReadRegisterMessage();
+    QByteArray trkReadMemoryMessage(uint addr, uint len);
+    QByteArray trkBreakpointMessage(uint addr, uint len, bool armMode = true);
+    void handleAndReportSetBreakpoint(const TrkResult &result);
+    void handleReadMemoryBuffered(const TrkResult &result);
+    void handleReadMemoryUnbuffered(const TrkResult &result);
+    void handleStepRange(const TrkResult &result);
+    void handleReadRegisters(const TrkResult &result);
+    void reportReadMemoryBuffered(const TrkResult &result);
+    void reportToGdb(const TrkResult &result);
+
+    // set breakpoints behind gdb's back
+    void handleSetTrkBreakpoint(const TrkResult &result);
+    void handleSetTrkMainBreakpoint(const TrkResult &result);
+
+    void readMemory(uint addr, uint len);
+    void interruptInferior();
+
+    trk::TrkDevice m_trkDevice;
+
+    //
+    // Gdb
+    //
+    struct GdbCommand
+    {
+        GdbCommand() : flags(0), callback(GdbCallback()), callbackName(0) {}
+
+        int flags;
+        GdbCallback callback;
+        const char *callbackName;
+        QString command;
+        QVariant cookie;
+        //QTime postTime;
+    };
+
+    void sendGdbMessage(const QString &msg,
+        GdbCallback callback = GdbCallback(),
+        const QVariant &cookie = QVariant());
+    Q_SLOT void handleGdbConnection();
+    Q_SLOT void readGdbServerCommand();
+    void readGdbResponse();
+    void handleGdbServerCommand(const QByteArray &cmd);
+    void sendGdbServerMessage(const QByteArray &msg,
+        const QByteArray &logNote = QByteArray());
+    void sendGdbServerMessageAfterTrkResponse(const QByteArray &msg,
+        const QByteArray &logNote = QByteArray());
+    void sendGdbServerAck();
+    bool sendGdbServerPacket(const QByteArray &packet, bool doFlush);
+
+    Q_SLOT void handleGdbReadyReadStandardError();
+    Q_SLOT void handleGdbReadyReadStandardOutput();
+    void logMessage(const QString &msg, bool force = false);
+    Q_SLOT void trkLogMessage(const QString &msg);
+
+    void handleInfoAddress(const GdbResult &result);
+    void handleInfoMainAddress(const GdbResult &result);
+
+    QTcpServer m_gdbServer;
+    QPointer<QTcpSocket> m_gdbConnection;
+    QByteArray m_gdbReadBuffer;
+    bool m_gdbAckMode;
+
+    QHash<int, GdbCommand> m_gdbCookieForToken;
+
+    //
+    // Rfcomm
+    //
+    Q_SLOT void handleRfcommReadyReadStandardError();
+    Q_SLOT void handleRfcommReadyReadStandardOutput();
+
+    // Debuggee state
+    Q_SLOT void executeCommand(const QString &msg);
+    trk::Session m_session; // global-ish data (process id, target information)
+    trk::Snapshot m_snapshot; // local-ish data (memory and registers)
+    int m_verbose;
+    bool m_serialFrame;
+    bool m_bufferedMemoryRead;
+};
+
+} // namespace Internal
+} // namespace Debugger
+
+#endif // DEBUGGER_SYMBIANADAPTER_H
diff --git a/src/plugins/debugger/symbian/symbianengine.cpp b/src/plugins/debugger/symbian/symbianengine.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..11c6b03c8ad2f81e78a2a2a3386be525fc05530d
--- /dev/null
+++ b/src/plugins/debugger/symbian/symbianengine.cpp
@@ -0,0 +1,66 @@
+/**************************************************************************
+**
+** 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.
+**
+**************************************************************************/
+
+#define QT_NO_CAST_FROM_ASCII
+
+#include "gdb/gdbengine.h"
+#include "symbianadapter.h"
+
+//#include "debuggerdialogs.h"
+
+#include <utils/qtcassert.h>
+#include <texteditor/itexteditor.h>
+#include <coreplugin/icore.h>
+#include <coreplugin/dialogs/ioptionspage.h>
+
+#include <QtCore/QDebug>
+#include <QtCore/QDir>
+#include <QtCore/QFileInfo>
+#include <QtCore/QMetaObject>
+#include <QtCore/QTime>
+#include <QtCore/QTimer>
+#include <QtCore/QTextStream>
+
+
+namespace Debugger {
+namespace Internal {
+
+
+IDebuggerEngine *createSymbianEngine(DebuggerManager *parent,
+    QList<Core::IOptionsPage*> *opts)
+{
+    Q_UNUSED(opts);
+    //opts->push_back(new GdbOptionsPage);
+    return new GdbEngine(parent, new SymbianAdapter);
+}
+
+} // namespace Internal
+} // namespace Debugger
+
+
diff --git a/tests/manual/trk/trkdevicex.cpp b/src/plugins/debugger/symbian/trkclient.cpp
similarity index 93%
rename from tests/manual/trk/trkdevicex.cpp
rename to src/plugins/debugger/symbian/trkclient.cpp
index 31382de3f03c237a043171487cf419c1d0388abf..5ae9766ac5abbab34f6b12fb051226c26b9a0776 100644
--- a/tests/manual/trk/trkdevicex.cpp
+++ b/src/plugins/debugger/symbian/trkclient.cpp
@@ -27,7 +27,7 @@
 **
 **************************************************************************/
 
-#include "trkdevicex.h"
+#include "trkclient.h"
 #include "trkutils.h"
 
 #include <QtCore/QString>
@@ -35,7 +35,6 @@
 #include <QtCore/QQueue>
 #include <QtCore/QHash>
 #include <QtCore/QMap>
-#include <QtCore/QSharedPointer>
 
 #ifdef Q_OS_WIN
 #  include <windows.h>
@@ -117,14 +116,12 @@ struct TrkMessage
     QByteArray data;
     QVariant cookie;
     Callback callback;
-    bool invokeOnNAK;
 };
 
 TrkMessage::TrkMessage(byte c, byte t, Callback cb) :
     code(c),
     token(t),
-    callback(cb),
-    invokeOnNAK(false)
+    callback(cb)
 {
 }
 
@@ -144,8 +141,7 @@ public:
 
     // Enqueue messages.
     void queueTrkMessage(byte code, Callback callback,
-                        const QByteArray &data, const QVariant &cookie,
-                        bool invokeOnNAK);
+                        const QByteArray &data, const QVariant &cookie);
     void queueTrkInitialPing();
 
     // Call this from the device read notification with the results.
@@ -184,14 +180,13 @@ byte TrkWriteQueue::nextTrkWriteToken()
 }
 
 void TrkWriteQueue::queueTrkMessage(byte code, Callback callback,
-    const QByteArray &data, const QVariant &cookie, bool invokeOnNAK)
+    const QByteArray &data, const QVariant &cookie)
 {
     const byte token = code == TRK_WRITE_QUEUE_NOOP_CODE ?
                                 byte(0) : nextTrkWriteToken();
     TrkMessage msg(code, token, callback);
     msg.data = data;
     msg.cookie = cookie;
-    msg.invokeOnNAK = invokeOnNAK;
     trkWriteQueue.append(msg);
 }
 
@@ -233,16 +228,14 @@ void TrkWriteQueue::notifyWriteResult(bool ok)
 void TrkWriteQueue::slotHandleResult(const TrkResult &result)
 {
     trkWriteBusy = false;
-    if (result.code != TrkNotifyAck && result.code != TrkNotifyNak)
-        return;
+    //if (result.code != TrkNotifyAck && result.code != TrkNotifyNak)
+    //    return;
     // Find which request the message belongs to and invoke callback
     // if ACK or on NAK if desired.
     const TokenMessageMap::iterator it = writtenTrkMessages.find(result.token);
     if (it == writtenTrkMessages.end())
         return;
-    const bool invokeCB = it.value().callback
-                          && (result.code == TrkNotifyAck || it.value().invokeOnNAK);
-
+    const bool invokeCB = it.value().callback;
     if (invokeCB) {
         TrkResult result1 = result;
         result1.cookie = it.value().cookie;
@@ -257,8 +250,18 @@ void TrkWriteQueue::queueTrkInitialPing()
     trkWriteQueue.append(TrkMessage(0, 0));
 }
 
-struct TrkDevicePrivate {
+
+///////////////////////////////////////////////////////////////////////
+//
+// TrkDevicePrivate
+//
+///////////////////////////////////////////////////////////////////////
+
+struct TrkDevicePrivate
+{
     TrkDevicePrivate();
+
+    TrkWriteQueue queue;
 #ifdef Q_OS_WIN
     HANDLE hdevice;
 #else
@@ -298,11 +301,13 @@ TrkDevicePrivate::TrkDevicePrivate() :
 
 TrkDevice::TrkDevice(QObject *parent) :
     QObject(parent),
-    d(new TrkDevicePrivate),
-    qd(new TrkWriteQueue)
+    d(new TrkDevicePrivate)
+{}
+
+TrkDevice::~TrkDevice()
 {
-    connect(this, SIGNAL(messageReceived(trk::TrkResult)),
-        this, SLOT(slotHandleResult(trk::TrkResult)));
+    close();
+    delete d;
 }
 
 bool TrkDevice::open(const QString &port, QString *errorMessage)
@@ -355,14 +360,6 @@ bool TrkDevice::open(const QString &port, QString *errorMessage)
 #endif
 }
 
-
-TrkDevice::~TrkDevice()
-{
-    close();
-    delete d;
-    delete qd;
-}
-
 void TrkDevice::close()
 {
     if (!isOpen())
@@ -492,6 +489,7 @@ void TrkDevice::tryTrkRead()
     while (extractResult(&d->trkReadBuffer, d->serialFrame, &r, &rawData)) {
         //if (verbose())
         //    logMessage("Read TrkResult " + r.data.toHex());
+        d->queue.slotHandleResult(r);
         emit messageReceived(r);
         if (!rawData.isEmpty())
             emit rawDataReceived(rawData);
@@ -512,14 +510,14 @@ void TrkDevice::emitError(const QString &s)
 }
 
 void TrkDevice::sendTrkMessage(byte code, Callback callback,
-     const QByteArray &data, const QVariant &cookie, bool invokeOnNAK)
+     const QByteArray &data, const QVariant &cookie)
 {
-    qd->queueTrkMessage(code, callback, data, cookie, invokeOnNAK);
+    d->queue.queueTrkMessage(code, callback, data, cookie);
 }
 
 void TrkDevice::sendTrkInitialPing()
 {
-    qd->queueTrkInitialPing();
+    d->queue.queueTrkInitialPing();
 }
 
 bool TrkDevice::sendTrkAck(byte token)
@@ -535,10 +533,10 @@ bool TrkDevice::sendTrkAck(byte token)
 void TrkDevice::tryTrkWrite()
 {
     TrkMessage message;
-    if (!qd->pendingMessage(&message))
+    if (!d->queue.pendingMessage(&message))
         return;
     const bool success = trkWriteRawMessage(message);
-    qd->notifyWriteResult(success);
+    d->queue.notifyWriteResult(success);
 }
 
 bool TrkDevice::trkWriteRawMessage(const TrkMessage &msg)
@@ -553,10 +551,5 @@ bool TrkDevice::trkWriteRawMessage(const TrkMessage &msg)
     return rc;
 }
 
-void TrkDevice::slotHandleResult(const TrkResult &result)
-{
-    qd->slotHandleResult(result);
-}
-
 } // namespace trk
 
diff --git a/tests/manual/trk/trkdevicex.h b/src/plugins/debugger/symbian/trkclient.h
similarity index 92%
rename from tests/manual/trk/trkdevicex.h
rename to src/plugins/debugger/symbian/trkclient.h
index 9d0e9da0dcc62c0cf9bc925f26f194c645d8e7fe..5a7a7440775ef782e88035ae5f0396faf2012e3b 100644
--- a/tests/manual/trk/trkdevicex.h
+++ b/src/plugins/debugger/symbian/trkclient.h
@@ -46,8 +46,6 @@ namespace trk {
 struct TrkResult;
 struct TrkMessage;
 struct TrkDevicePrivate;
-class TrkWriteQueue;
-struct TrkWriteQueueIODevicePrivate;
 
 /* TrkDevice: Implements a Windows COM or Linux device for
  * Trk communications. Provides synchronous write and asynchronous
@@ -106,9 +104,7 @@ public:
     void sendTrkMessage(unsigned char code,
                         Callback callBack = Callback(),
                         const QByteArray &data = QByteArray(),
-                        const QVariant &cookie = QVariant(),
-                        // Invoke callback on receiving NAK, too.
-                        bool invokeOnNAK = false);
+                        const QVariant &cookie = QVariant());
 
     // Enqeue an initial ping
     void sendTrkInitialPing();
@@ -116,15 +112,11 @@ public:
     // Send an Ack synchronously, bypassing the queue
     bool sendTrkAck(unsigned char token);
 
-private slots:
-    void slotHandleResult(const trk::TrkResult &);
-
 private:
     void tryTrkWrite();
     bool trkWriteRawMessage(const TrkMessage &msg);
 
     TrkDevicePrivate *d;
-    TrkWriteQueue *qd;
 };
 
 } // namespace trk
diff --git a/tests/manual/trk/trkfunctor.h b/src/plugins/debugger/symbian/trkfunctor.h
similarity index 97%
rename from tests/manual/trk/trkfunctor.h
rename to src/plugins/debugger/symbian/trkfunctor.h
index 69a67e97a616a45d4457a2b65cdbe1fbeb3e1e0b..4b0d366912063d973d7f2ccfecba4d042201ed89 100644
--- a/tests/manual/trk/trkfunctor.h
+++ b/src/plugins/debugger/symbian/trkfunctor.h
@@ -27,11 +27,14 @@
 **
 **************************************************************************/
 
-#ifndef _TRK_FUNCTOR_H_
-#define _TRK_FUNCTOR_H_
+#ifndef DEBUGGER_TRK_FUNCTOR_H
+#define DEBUGGER_TRK_FUNCTOR_H
 
 #include <QtGlobal>
 
+
+// FIXME: rename into something less TRK-specific
+
 namespace trk {
 namespace Internal {
 /* Helper class for the 1-argument functor:
diff --git a/tests/manual/trk/trkutils.cpp b/src/plugins/debugger/symbian/trkutils.cpp
similarity index 96%
rename from tests/manual/trk/trkutils.cpp
rename to src/plugins/debugger/symbian/trkutils.cpp
index 81925c07d674e0efb19afb836f658c193eaf47a3..4036b2ad6563f30ca734393ffd9a6b71f86dd531 100644
--- a/tests/manual/trk/trkutils.cpp
+++ b/src/plugins/debugger/symbian/trkutils.cpp
@@ -43,6 +43,11 @@ QByteArray hexNumber(uint n, int digits)
     return QByteArray(digits - ba.size(), '0') + ba;
 }
 
+QByteArray hexxNumber(uint n, int digits)
+{
+    return "0x" + hexNumber(n, digits);
+}
+
 TrkResult::TrkResult() :
     code(0),
     token(0),
@@ -345,5 +350,16 @@ int TrkResult::errorCode() const
         return errorCode;
     return isNAK ? 0xff : 0;
 }
+
+QString TrkResult::errorString() const
+{
+    // NAK means always error, else data sized 1 with a non-null element
+    if (code == 0xff)
+        return "NAK";
+    if (data.size() < 1)
+        return "Unknown error packet";
+    return errorMessage(data.at(0));
+}
+
 } // namespace trk
 
diff --git a/tests/manual/trk/trkutils.h b/src/plugins/debugger/symbian/trkutils.h
similarity index 96%
rename from tests/manual/trk/trkutils.h
rename to src/plugins/debugger/symbian/trkutils.h
index 42df54b680ddc48ccbadb3255e65ade30974de54..6f1b280eb85b4d23e1eaca53655ea314ac14a2f8 100644
--- a/tests/manual/trk/trkutils.h
+++ b/src/plugins/debugger/symbian/trkutils.h
@@ -72,6 +72,7 @@ enum Command {
 QByteArray decode7d(const QByteArray &ba);
 QByteArray encode7d(const QByteArray &ba);
 
+inline byte extractByte(const char *data) { return *data; }
 ushort extractShort(const char *data);
 uint extractInt(const char *data);
 
@@ -143,7 +144,7 @@ struct Session
     uint tid;
     uint codeseg;
     uint dataseg;
-    QHash<uint, uint> tokenToBreakpointIndex;
+    QHash<uint, uint> addressToBP;
 
     // Gdb request
     uint currentThread;
@@ -177,6 +178,7 @@ struct TrkResult
     QString toString() const;
     // 0 for no error.
     int errorCode() const;
+    QString errorString() const;
 
     byte code;
     byte token;
@@ -192,9 +194,9 @@ ushort isValidTrkResult(const QByteArray &buffer, bool serialFrame);
 bool extractResult(QByteArray *buffer, bool serialFrame, TrkResult *r, QByteArray *rawData = 0);
 QByteArray errorMessage(byte code);
 QByteArray hexNumber(uint n, int digits = 0);
+QByteArray hexxNumber(uint n, int digits = 0); // prepends '0x', too
 uint swapEndian(uint in);
 
-
 } // namespace trk
 
 #endif // DEBUGGER_TRK_UTILS
diff --git a/src/plugins/projectexplorer/abstractprocessstep.cpp b/src/plugins/projectexplorer/abstractprocessstep.cpp
index a766a1e5a8b876490417b72baf5ba3c122395d79..e3b7757881ea3ab21ea8545db5c4491bb694535f 100644
--- a/src/plugins/projectexplorer/abstractprocessstep.cpp
+++ b/src/plugins/projectexplorer/abstractprocessstep.cpp
@@ -58,7 +58,13 @@ void AbstractProcessStep::setCommand(const QString &buildConfiguration, const QS
 
 QString AbstractProcessStep::command(const QString &buildConfiguration) const
 {
-    return value(buildConfiguration, PROCESS_COMMAND).toString();
+    QString result = value(buildConfiguration, PROCESS_COMMAND).toString();
+    if (QFileInfo(result).isRelative()) {
+        QString searchInPath = environment(buildConfiguration).searchInPath(result);
+        if (!searchInPath.isEmpty())
+            result = searchInPath;
+    }
+    return result;
 }
 
 void AbstractProcessStep::setWorkingDirectory(const QString &buildConfiguration, const QString &workingDirectory)
diff --git a/src/plugins/qmlprojectmanager/qmlproject.cpp b/src/plugins/qmlprojectmanager/qmlproject.cpp
index a0dc6873c93184aadf70d98544d1a2b617fb8698..2d61bd50366153855ede723cdc2b2cc4c37201cb 100644
--- a/src/plugins/qmlprojectmanager/qmlproject.cpp
+++ b/src/plugins/qmlprojectmanager/qmlproject.cpp
@@ -344,12 +344,7 @@ QString QmlRunConfiguration::type() const
 
 QString QmlRunConfiguration::executable() const
 {
-    if (! QFile::exists(m_qmlViewer)) {
-        QMessageBox::information(Core::ICore::instance()->mainWindow(),
-                                 tr("QML Viewer"),
-                                 tr("Could not find the qmlviewer executable, please specify one."));
-    }
-
+    // No need to verify if the QML Viewer exists. The console will tell us anyway when we try to launch it.
     return m_qmlViewer;
 }
 
diff --git a/src/plugins/texteditor/basetextdocument.cpp b/src/plugins/texteditor/basetextdocument.cpp
index 8de81100d8cd9c8b4425cc999864b76478dfce82..6da82ccdf594ca4b9ddd8aebf9778c419a3c653e 100644
--- a/src/plugins/texteditor/basetextdocument.cpp
+++ b/src/plugins/texteditor/basetextdocument.cpp
@@ -93,7 +93,7 @@ bool BaseTextDocument::save(const QString &fileName)
 
     cursor.beginEditBlock();
     if (m_storageSettings.m_cleanWhitespace)
-        cleanWhitespace(cursor, m_storageSettings.m_inEntireDocument);
+        cleanWhitespace(cursor, m_storageSettings.m_cleanIndentation, m_storageSettings.m_inEntireDocument);
     if (m_storageSettings.m_addFinalNewLine)
         ensureFinalNewLine(cursor);
     cursor.endEditBlock();
@@ -301,23 +301,28 @@ void BaseTextDocument::setSyntaxHighlighter(QSyntaxHighlighter *highlighter)
 
 
 
-void BaseTextDocument::cleanWhitespace()
+void BaseTextDocument::cleanWhitespace(const QTextCursor &cursor)
 {
-    QTextCursor cursor(m_document);
-    cursor.beginEditBlock();
-    cleanWhitespace(cursor, true);
-    if (m_storageSettings.m_addFinalNewLine)
-        ensureFinalNewLine(cursor);
-    cursor.endEditBlock();
+    bool hasSelection = cursor.hasSelection();
+    QTextCursor copyCursor = cursor;
+    copyCursor.beginEditBlock();
+    cleanWhitespace(copyCursor, true, true);
+    if (!hasSelection)
+        ensureFinalNewLine(copyCursor);
+    copyCursor.endEditBlock();
 }
 
-void BaseTextDocument::cleanWhitespace(QTextCursor& cursor, bool inEntireDocument)
+void BaseTextDocument::cleanWhitespace(QTextCursor& cursor, bool cleanIndentation, bool inEntireDocument)
 {
 
     TextEditDocumentLayout *documentLayout = qobject_cast<TextEditDocumentLayout*>(m_document->documentLayout());
 
-    QTextBlock block = m_document->firstBlock();
-    while (block.isValid()) {
+    QTextBlock block = m_document->findBlock(cursor.selectionStart());
+    QTextBlock end;
+    if (cursor.hasSelection())
+        end = m_document->findBlock(cursor.selectionEnd()-1).next();
+
+    while (block.isValid() && block != end) {
 
         if (inEntireDocument || block.revision() > documentLayout->lastSaveRevision) {
 
@@ -327,7 +332,7 @@ void BaseTextDocument::cleanWhitespace(QTextCursor& cursor, bool inEntireDocumen
                 cursor.movePosition(QTextCursor::PreviousCharacter, QTextCursor::KeepAnchor, trailing);
                 cursor.removeSelectedText();
             }
-            if (m_storageSettings.m_cleanIndentation && !m_tabSettings.isIndentationClean(blockText)) {
+            if (cleanIndentation && !m_tabSettings.isIndentationClean(blockText)) {
                 cursor.setPosition(block.position());
                 int firstNonSpace = m_tabSettings.firstNonSpace(blockText);
                 if (firstNonSpace == blockText.length()) {
diff --git a/src/plugins/texteditor/basetextdocument.h b/src/plugins/texteditor/basetextdocument.h
index 88e1c609a132fa5dc5f3ae6af81616ac9230f7e6..eaf37c91caf2ae40acca18e649522dcdd07ff264 100644
--- a/src/plugins/texteditor/basetextdocument.h
+++ b/src/plugins/texteditor/basetextdocument.h
@@ -110,7 +110,7 @@ public:
 
     void reload(QTextCodec *codec);
 
-    void cleanWhitespace();
+    void cleanWhitespace(const QTextCursor &cursor);
 
 signals:
     void titleChanged(QString title);
@@ -146,7 +146,7 @@ private:
     bool m_hasDecodingError;
     QByteArray m_decodingErrorSample;
 
-    void cleanWhitespace(QTextCursor& cursor, bool onlyInModifiedLines);
+    void cleanWhitespace(QTextCursor& cursor, bool cleanIndentation, bool inEntireDocument);
     void ensureFinalNewLine(QTextCursor& cursor);
 };
 
diff --git a/src/plugins/texteditor/basetexteditor.cpp b/src/plugins/texteditor/basetexteditor.cpp
index 8c23d975df5d876a7a04d7b85ad8c6d76b2df5ff..cce27c4c21b3a2ebf59a8e560abafe027f5dde51 100644
--- a/src/plugins/texteditor/basetexteditor.cpp
+++ b/src/plugins/texteditor/basetexteditor.cpp
@@ -833,7 +833,7 @@ void BaseTextEditor::moveLineUpDown(bool up)
 
 void BaseTextEditor::cleanWhitespace()
 {
-    d->m_document->cleanWhitespace();
+    d->m_document->cleanWhitespace(textCursor());
 }
 
 void BaseTextEditor::keyPressEvent(QKeyEvent *e)
@@ -887,13 +887,18 @@ void BaseTextEditor::keyPressEvent(QKeyEvent *e)
         QTextCursor cursor = textCursor();
         if (d->m_inBlockSelectionMode)
             cursor.clearSelection();
-        if (d->m_document->tabSettings().m_autoIndent) {
+        const TabSettings &ts = d->m_document->tabSettings();
+        if (ts.m_autoIndent) {
             cursor.beginEditBlock();
             cursor.insertBlock();
             indent(document(), cursor, QChar::Null);
             cursor.endEditBlock();
         } else {
+            cursor.beginEditBlock();
+            QString previousBlockText = cursor.block().text();
             cursor.insertBlock();
+            cursor.insertText(ts.indentationString(previousBlockText));
+            cursor.endEditBlock();
         }
         e->accept();
         setTextCursor(cursor);
@@ -1337,6 +1342,16 @@ bool BaseTextEditor::codeFoldingSupported() const
     return d->m_codeFoldingSupported;
 }
 
+void BaseTextEditor::setMouseNavigationEnabled(bool b)
+{
+    d->m_mouseNavigationEnabled = b;
+}
+
+bool BaseTextEditor::mouseNavigationEnabled() const
+{
+    return d->m_mouseNavigationEnabled;
+}
+
 void BaseTextEditor::setRevisionsVisible(bool b)
 {
     d->m_revisionsVisible = b;
@@ -1372,12 +1387,14 @@ BaseTextEditorPrivate::BaseTextEditorPrivate()
     m_marksVisible(false),
     m_codeFoldingVisible(false),
     m_codeFoldingSupported(false),
+    m_mouseNavigationEnabled(true),
     m_revisionsVisible(false),
     m_lineNumbersVisible(true),
     m_highlightCurrentLine(true),
     m_requestMarkEnabled(true),
     m_lineSeparatorsAllowed(false),
     m_visibleWrapColumn(0),
+    m_showingLink(false),
     m_editable(0),
     m_actionHack(0),
     m_inBlockSelectionMode(false),
@@ -2721,6 +2738,32 @@ void BaseTextEditorPrivate::clearVisibleCollapsedBlock()
 void BaseTextEditor::mouseMoveEvent(QMouseEvent *e)
 {
     d->m_lastEventWasBlockSelectionEvent = (e->modifiers() & Qt::AltModifier);
+
+    bool linkFound = false;
+
+    if (d->m_mouseNavigationEnabled && e->modifiers() & Qt::ControlModifier) {
+        // Link emulation behaviour for 'go to definition'
+        const QTextCursor cursor = cursorForPosition(e->pos());
+
+        // Check that the mouse was actually on the text somewhere
+        bool onText = cursorRect(cursor).right() >= e->x();
+        if (!onText) {
+            QTextCursor nextPos = cursor;
+            nextPos.movePosition(QTextCursor::Right);
+            onText = cursorRect(nextPos).right() >= e->x();
+        }
+
+        const Link link = findLinkAt(cursor, false);
+
+        if (onText && link.isValid()) {
+            showLink(link);
+            linkFound = true;
+        }
+    }
+
+    if (!linkFound)
+        clearLink();
+
     if (e->buttons() == Qt::NoButton) {
         const QTextBlock collapsedBlock = collapsedBlockAt(e->pos());
         const int blockNumber = collapsedBlock.next().blockNumber();
@@ -2767,6 +2810,38 @@ void BaseTextEditor::mousePressEvent(QMouseEvent *e)
     QPlainTextEdit::mousePressEvent(e);
 }
 
+void BaseTextEditor::mouseReleaseEvent(QMouseEvent *e)
+{
+    if (d->m_mouseNavigationEnabled && e->modifiers() & Qt::ControlModifier
+        && !(e->modifiers() & Qt::ShiftModifier)
+        && e->button() == Qt::LeftButton) {
+
+        const QTextCursor cursor = cursorForPosition(e->pos());
+        if (openLink(findLinkAt(cursor))) {
+            clearLink();
+            return;
+        }
+    }
+
+    QPlainTextEdit::mouseReleaseEvent(e);
+}
+
+void BaseTextEditor::leaveEvent(QEvent *e)
+{
+    // Clear link emulation when the mouse leaves the editor
+    clearLink();
+    QPlainTextEdit::leaveEvent(e);
+}
+
+void BaseTextEditor::keyReleaseEvent(QKeyEvent *e)
+{
+    // Clear link emulation when Ctrl is released
+    if (e->key() == Qt::Key_Control)
+        clearLink();
+
+    QPlainTextEdit::keyReleaseEvent(e);
+}
+
 void BaseTextEditor::extraAreaLeaveEvent(QEvent *)
 {
     // fake missing mouse move event from Qt
@@ -2833,7 +2908,7 @@ void BaseTextEditor::extraAreaMouseEvent(QMouseEvent *e)
                             document()->findBlockByNumber(d->m_highlightBlocksInfo.open.last()).position()
                             );
                     QTextBlock c = cursor.block();
-                    if (!TextBlockUserData::canCollapse(c))
+                    if (TextBlockUserData::hasCollapseAfter(c.previous()))
                         c = c.previous();
                     toggleBlockVisible(c);
                     d->moveCursorVisible(false);
@@ -3119,17 +3194,14 @@ void BaseTextEditor::handleBackspaceKey()
             continue;
         previousIndent = tabSettings.columnAt(previousNonEmptyBlockText,
                                               tabSettings.firstNonSpace(previousNonEmptyBlockText));
-        if (previousIndent < indent)
+        if (previousIndent < indent) {
+            cursor.beginEditBlock();
+            cursor.setPosition(currentBlock.position(), QTextCursor::KeepAnchor);
+            cursor.insertText(tabSettings.indentationString(previousNonEmptyBlockText));
+            cursor.endEditBlock();
             break;
+        }
     }
-
-    if (previousIndent >= indent)
-        previousIndent = 0;
-
-    cursor.beginEditBlock();
-    cursor.setPosition(currentBlock.position(), QTextCursor::KeepAnchor);
-    cursor.insertText(tabSettings.indentationString(0, previousIndent));
-    cursor.endEditBlock();
 }
 
 void BaseTextEditor::wheelEvent(QWheelEvent *e)
@@ -3186,6 +3258,50 @@ void BaseTextEditor::indent(QTextDocument *doc, const QTextCursor &cursor, QChar
     }
 }
 
+BaseTextEditor::Link BaseTextEditor::findLinkAt(const QTextCursor &, bool)
+{
+    return Link();
+}
+
+bool BaseTextEditor::openLink(const Link &link)
+{
+    if (link.fileName.isEmpty())
+        return false;
+
+    if (baseTextDocument()->fileName() == link.fileName) {
+        Core::EditorManager *editorManager = Core::EditorManager::instance();
+        editorManager->addCurrentPositionToNavigationHistory();
+        gotoLine(link.line, link.column);
+        setFocus();
+        return true;
+    }
+
+    return openEditorAt(link.fileName, link.line, link.column);
+}
+
+void BaseTextEditor::showLink(const Link &link)
+{
+    QTextEdit::ExtraSelection sel;
+    sel.cursor = textCursor();
+    sel.cursor.setPosition(link.pos);
+    sel.cursor.setPosition(link.pos + link.length, QTextCursor::KeepAnchor);
+    sel.format = d->m_linkFormat;
+    sel.format.setFontUnderline(true);
+    setExtraSelections(OtherSelection, QList<QTextEdit::ExtraSelection>() << sel);
+    viewport()->setCursor(Qt::PointingHandCursor);
+    d->m_showingLink = true;
+}
+
+void BaseTextEditor::clearLink()
+{
+    if (!d->m_showingLink)
+        return;
+
+    setExtraSelections(OtherSelection, QList<QTextEdit::ExtraSelection>());
+    viewport()->setCursor(Qt::IBeamCursor);
+    d->m_showingLink = false;
+}
+
 void BaseTextEditorPrivate::updateMarksBlock(const QTextBlock &block)
 {
     if (const TextBlockUserData *userData = TextEditDocumentLayout::testUserData(block))
@@ -4005,8 +4121,8 @@ void BaseTextEditor::unCommentSelection()
 void BaseTextEditor::showEvent(QShowEvent* e)
 {
     if (!d->m_fontSettings.isEmpty()) {
-	setFontSettings(d->m_fontSettings);
-	d->m_fontSettings.clear();
+        setFontSettings(d->m_fontSettings);
+        d->m_fontSettings.clear();
     }
     QPlainTextEdit::showEvent(e);
 }
@@ -4015,11 +4131,12 @@ void BaseTextEditor::showEvent(QShowEvent* e)
 void BaseTextEditor::setFontSettingsIfVisible(const TextEditor::FontSettings &fs)
 {
     if (!isVisible()) {
-	d->m_fontSettings = fs;
-	return;
+        d->m_fontSettings = fs;
+        return;
     }
     setFontSettings(fs);
 }
+
 void BaseTextEditor::setFontSettings(const TextEditor::FontSettings &fs)
 {
     const QTextCharFormat textFormat = fs.toTextCharFormat(QLatin1String(Constants::C_TEXT));
@@ -4030,6 +4147,7 @@ void BaseTextEditor::setFontSettings(const TextEditor::FontSettings &fs)
     const QTextCharFormat parenthesesFormat = fs.toTextCharFormat(QLatin1String(Constants::C_PARENTHESES));
     d->m_currentLineFormat = fs.toTextCharFormat(QLatin1String(Constants::C_CURRENT_LINE));
     d->m_currentLineNumberFormat = fs.toTextCharFormat(QLatin1String(Constants::C_CURRENT_LINE_NUMBER));
+    d->m_linkFormat = fs.toTextCharFormat(QLatin1String(TextEditor::Constants::C_LINK));
     d->m_ifdefedOutFormat = fs.toTextCharFormat(QLatin1String(Constants::C_DISABLED_CODE));
     QFont font(textFormat.font());
 
@@ -4082,6 +4200,7 @@ void BaseTextEditor::setDisplaySettings(const DisplaySettings &ds)
     setCodeFoldingVisible(ds.m_displayFoldingMarkers);
     setHighlightCurrentLine(ds.m_highlightCurrentLine);
     setRevisionsVisible(ds.m_markTextChanges);
+    setMouseNavigationEnabled(ds.m_mouseNavigation);
 
     if (d->m_displaySettings.m_visualizeWhitespace != ds.m_visualizeWhitespace) {
         if (QSyntaxHighlighter *highlighter = baseTextDocument()->syntaxHighlighter())
diff --git a/src/plugins/texteditor/basetexteditor.h b/src/plugins/texteditor/basetexteditor.h
index 906e73a14fe2c8cb2c221956511f267690148f41..17a67d3b0a9bd4bde8cdc329cad1db02f32ee01d 100644
--- a/src/plugins/texteditor/basetexteditor.h
+++ b/src/plugins/texteditor/basetexteditor.h
@@ -145,13 +145,10 @@ public:
 
     inline static bool hasCollapseAfter(const QTextBlock & block)
     {
-        if (!block.isValid())
-            return false;
-        TextBlockUserData *data = static_cast<TextBlockUserData*>(block.userData());
-        if (data && data->collapseMode() != NoCollapse) {
+        if (!block.isValid()) {
             return false;
         } else if (block.next().isValid()) {
-            data = static_cast<TextBlockUserData*>(block.next().userData());
+            TextBlockUserData *data = static_cast<TextBlockUserData*>(block.next().userData());
             if (data && data->collapseMode() == TextBlockUserData::CollapseThis &&  !data->m_ifdefedOut)
                 return true;
         }
@@ -277,8 +274,7 @@ private:
 };
 
 
-class TEXTEDITOR_EXPORT BaseTextEditor
-  : public QPlainTextEdit
+class TEXTEDITOR_EXPORT BaseTextEditor : public QPlainTextEdit
 {
     Q_OBJECT
 
@@ -348,6 +344,9 @@ public:
     void setCodeFoldingSupported(bool b);
     bool codeFoldingSupported() const;
 
+    void setMouseNavigationEnabled(bool b);
+    bool mouseNavigationEnabled() const;
+
     void setRevisionsVisible(bool b);
     bool revisionsVisible() const;
 
@@ -499,14 +498,54 @@ protected:
     void timerEvent(QTimerEvent *);
     void mouseMoveEvent(QMouseEvent *);
     void mousePressEvent(QMouseEvent *);
+    void mouseReleaseEvent(QMouseEvent *);
+    void leaveEvent(QEvent *);
+    void keyReleaseEvent(QKeyEvent *);
 
-    // Rertuns true if key triggers an indent.
+    // Returns true if key triggers an indent.
     virtual bool isElectricCharacter(const QChar &ch) const;
     // Indent a text block based on previous line. Default does nothing
     virtual void indentBlock(QTextDocument *doc, QTextBlock block, QChar typedChar);
     // Indent at cursor. Calls indentBlock for selection or current line.
     virtual void indent(QTextDocument *doc, const QTextCursor &cursor, QChar typedChar);
 
+    struct Link
+    {
+        Link(const QString &fileName = QString(),
+             int line = 0,
+             int column = 0)
+            : pos(-1)
+            , length(-1)
+            , fileName(fileName)
+            , line(line)
+            , column(column)
+        {}
+
+        bool isValid() const
+        { return !(pos == -1 || length == -1); }
+
+        int pos;           // Link position
+        int length;        // Link length
+
+        QString fileName;  // Target file
+        int line;          // Target line
+        int column;        // Target column
+    };
+
+    /*!
+       Reimplement this function to enable code navigation.
+
+       \a resolveTarget is set to true when the target of the link is relevant
+       (it isn't until the link is used).
+     */
+    virtual Link findLinkAt(const QTextCursor &, bool resolveTarget = true);
+
+    /*!
+       Reimplement this function if you want to customize the way a link is
+       opened. Returns whether the link was opened succesfully.
+     */
+    virtual bool openLink(const Link &link);
+
 protected slots:
     virtual void slotUpdateExtraAreaWidth();
     virtual void slotModificationChanged(bool);
@@ -540,6 +579,8 @@ private:
 
     QTextBlock collapsedBlockAt(const QPoint &pos, QRect *box = 0) const;
 
+    void showLink(const Link &);
+    void clearLink();
 
     // parentheses matcher
 private slots:
diff --git a/src/plugins/texteditor/basetexteditor_p.h b/src/plugins/texteditor/basetexteditor_p.h
index dbf5b66d1e884b0a8850cfef2aa1a100099c4a75..1956f858800a807347a8c0938512aa69fc3a96d7 100644
--- a/src/plugins/texteditor/basetexteditor_p.h
+++ b/src/plugins/texteditor/basetexteditor_p.h
@@ -194,6 +194,7 @@ public:
     uint m_marksVisible : 1;
     uint m_codeFoldingVisible : 1;
     uint m_codeFoldingSupported : 1;
+    uint m_mouseNavigationEnabled : 1;
     uint m_revisionsVisible : 1;
     uint m_lineNumbersVisible : 1;
     uint m_highlightCurrentLine : 1;
@@ -201,6 +202,9 @@ public:
     uint m_lineSeparatorsAllowed : 1;
     int m_visibleWrapColumn;
 
+    QTextCharFormat m_linkFormat;
+    bool m_showingLink;
+
     QTextCharFormat m_ifdefedOutFormat;
 
     QRegExp m_searchExpr;
@@ -226,7 +230,7 @@ public:
     QString copyBlockSelection();
     void removeBlockSelection(const QString &text = QString());
     bool m_moveLineUndoHack;
-    
+
     QTextCursor m_findScope;
     QTextCursor m_selectBlockAnchor;
 
diff --git a/src/plugins/texteditor/tabsettings.cpp b/src/plugins/texteditor/tabsettings.cpp
index e0225ce8bcdbb12bf17d711504ece37e8f797ca5..393434d90852ab7ca4431f98f674fa1c7713b6f0 100644
--- a/src/plugins/texteditor/tabsettings.cpp
+++ b/src/plugins/texteditor/tabsettings.cpp
@@ -110,6 +110,18 @@ int TabSettings::firstNonSpace(const QString &text) const
     return i;
 }
 
+QString TabSettings::indentationString(const QString &text) const
+{
+    return text.left(firstNonSpace(text));
+}
+
+
+int TabSettings::indentationColumn(const QString &text) const
+{
+    return columnAt(text, firstNonSpace(text));
+}
+
+
 int TabSettings::trailingWhitespaces(const QString &text) const
 {
     int i = 0;
@@ -225,7 +237,7 @@ void TabSettings::indentLine(QTextBlock block, int newIndent) const
     const int oldBlockLength = text.size();
 
     // Quickly check whether indenting is required.
-    if (oldBlockLength == 0 && newIndent == 0)
+    if (indentationColumn(text) == newIndent)
         return;
 
     const QString indentString = indentationString(0, newIndent);
@@ -234,12 +246,6 @@ void TabSettings::indentLine(QTextBlock block, int newIndent) const
     if (oldBlockLength == indentString.length() && text == indentString)
         return;
 
-    if (oldBlockLength > indentString.length() &&
-        text.startsWith(indentString) &&
-        !text.at(indentString.length()).isSpace()) {
-        return;
-    }
-
     QTextCursor cursor(block);
     cursor.beginEditBlock();
     cursor.movePosition(QTextCursor::StartOfBlock);
diff --git a/src/plugins/texteditor/tabsettings.h b/src/plugins/texteditor/tabsettings.h
index ec2c3dfe8ea35666a5728909a08725153f526c16..f26e0bb5ad99dae0824bc74d1268f051ed849fb7 100644
--- a/src/plugins/texteditor/tabsettings.h
+++ b/src/plugins/texteditor/tabsettings.h
@@ -63,6 +63,8 @@ struct TEXTEDITOR_EXPORT TabSettings
     int spacesLeftFromPosition(const QString &text, int position) const;
     int indentedColumn(int column, bool doIndent = true) const;
     QString indentationString(int startColumn, int targetColumn) const;
+    QString indentationString(const QString &text) const;
+    int indentationColumn(const QString &text) const;
 
     void indentLine(QTextBlock block, int newIndent) const;
 
diff --git a/src/shared/proparser/profileevaluator.cpp b/src/shared/proparser/profileevaluator.cpp
index c4718c084957a9e68adf00a1d04f5e357677ce88..d536a03ef0fea5490d362386e069310d3fdc8406 100644
--- a/src/shared/proparser/profileevaluator.cpp
+++ b/src/shared/proparser/profileevaluator.cpp
@@ -1139,10 +1139,11 @@ ProItem::ProItemReturn ProFileEvaluator::Private::visitBeginProFile(ProFile * pr
                 }
                 if (!qmake_cache.isEmpty()) {
                     qmake_cache = QDir::cleanPath(qmake_cache);
-                    if (evaluateFileInto(qmake_cache, &m_option->cache_valuemap, 0)) {
+                    QHash<QString, QStringList> cache_valuemap;
+                    if (evaluateFileInto(qmake_cache, &cache_valuemap, 0)) {
                         m_option->cachefile = qmake_cache;
                         if (m_option->qmakespec.isEmpty()) {
-                            const QStringList &vals = m_option->cache_valuemap.value(QLatin1String("QMAKESPEC"));
+                            const QStringList &vals = cache_valuemap.value(QLatin1String("QMAKESPEC"));
                             if (!vals.isEmpty())
                                 m_option->qmakespec = vals.first();
                         }
@@ -1196,8 +1197,9 @@ ProItem::ProItemReturn ProFileEvaluator::Private::visitBeginProFile(ProFile * pr
                     if (!evaluateFileInto(spec,
                                           &m_option->base_valuemap, &m_option->base_functions)) {
                         errorMessage(format("Could not read qmake configuration file %1").arg(spec));
-                    } else {
-                        evaluateFileInto(qmake_cache, &m_option->base_valuemap, 0);
+                    } else if (!m_option->cachefile.isEmpty()) {
+                        evaluateFileInto(m_option->cachefile,
+                                         &m_option->base_valuemap, &m_option->base_functions);
                     }
                 }
 
diff --git a/src/shared/proparser/profileevaluator.h b/src/shared/proparser/profileevaluator.h
index cba159c6b8f1ee9e03924d958933e17100fa3180..691dd78e02b30256c6ee604ab59f1b90c12f2bc6 100644
--- a/src/shared/proparser/profileevaluator.h
+++ b/src/shared/proparser/profileevaluator.h
@@ -88,8 +88,7 @@ public:
         friend class ProFileEvaluator;
         friend class ProFileEvaluator::Private;
         static QString field_sep; // Just a cache for quick construction
-        QHash<QString, QStringList> cache_valuemap; // Cached results of .qmake.cache
-        QHash<QString, QStringList> base_valuemap; // ~ and qmake.conf and default_pre.prf
+        QHash<QString, QStringList> base_valuemap; // Cached results of qmake.conf, .qmake.cache & default_pre.prf
         FunctionDefs base_functions;
         QStringList feature_roots;
     };
diff --git a/tests/manual/trk/adapter.pro b/tests/manual/trk/adapter.pro
index 22f4aa3cddb1785127a452b4ee5ee116deebe501..9ee1a95d8f7b3893881eb7b4100848872ce2c903 100644
--- a/tests/manual/trk/adapter.pro
+++ b/tests/manual/trk/adapter.pro
@@ -1,14 +1,20 @@
 
 TEMPLATE = app
 
+DEBUGGERHOME = ../../../src/plugins/debugger/symbian
+
+INCLUDEPATH *= $$DEBUGGERHOME
+
+UTILSDIR = ../../../src/libs
 QT = core network
 win32:CONFIG+=console
 
-HEADERS += trkutils.h \
-trkfunctor.h \
-trkdevice.h \
+HEADERS += \
+    $$DEBUGGERHOME/trkutils.h \
+    $$DEBUGGERHOME/trkfunctor.h \
+    $$PWD/trkdevice.h \
 
 SOURCES += \
-    adapter.cpp \
-    trkutils.cpp \
-    trkdevice.cpp
+    $$DEBUGGERHOME/trkutils.cpp \
+    $$PWD/trkdevice.cpp \
+    $$PWD/adapter.cpp \
diff --git a/tests/manual/trk/runner.cpp b/tests/manual/trk/runner.cpp
index eeb080ca0d8ec2128e0c2ab79a0f3099b0cb7359..4724df4d1799cb1bacb82c91c4ed31ec82355646 100755
--- a/tests/manual/trk/runner.cpp
+++ b/tests/manual/trk/runner.cpp
@@ -27,10 +27,8 @@
 **
 **************************************************************************/
 
-#include "trkutils.h"
-#include "trkdevicex.h"
+#include "symbianadapter.h"
 
-#include <QtCore/QCoreApplication>
 #include <QtCore/QDebug>
 #include <QtCore/QDir>
 #include <QtCore/QFile>
@@ -43,23 +41,53 @@
 #include <QtCore/QTextStream>
 #include <QtCore/QTimer>
 
+#include <QtGui/QAction>
 #include <QtGui/QApplication>
+#include <QtGui/QMainWindow>
 #include <QtGui/QKeyEvent>
 #include <QtGui/QTextBlock>
 #include <QtGui/QTextEdit>
+#include <QtGui/QToolBar>
 
 #include <QtNetwork/QTcpServer>
 #include <QtNetwork/QTcpSocket>
 #include <QtNetwork/QLocalServer>
 #include <QtNetwork/QLocalSocket>
 
+/*
+fetch-register          p                       info registers
+set-register            P                       set
+binary-download         X                       load, set
+read-aux-vector         qXfer:auxv:read         info auxv
+symbol-lookup           qSymbol                 Detecting multiple threads
+attach                  vAttach                 attach
+verbose-resume          vCont                   Stepping or resuming multiple threads
+run                     vRun                    run
+software-breakpoint     Z0                      break
+hardware-breakpoint     Z1                      hbreak
+write-watchpoint        Z2                      watch
+read-watchpoint         Z3                      rwatch
+access-watchpoint       Z4                      awatch
+target-features         qXfer:features:read     set architecture
+library-info            qXfer:libraries:read    info sharedlibrary
+memory-map              qXfer:memory-map:read   info mem
+read-spu-object         qXfer:spu:read          info spu
+write-spu-object        qXfer:spu:write         info spu
+get-thread-local-
+storage-address         qGetTLSAddr             Displaying __thread variables
+supported-packets       qSupported              Remote communications parameters
+pass-signals            QPassSignals            handle signal
+hostio-close-packet     vFile:close             remote get, remote put
+hostio-open-packet      vFile:open              remote get, remote put
+hostio-pread-packet     vFile:pread             remote get, remote put
+hostio-pwrite-packet    vFile:pwrite            remote get, remote put
+hostio-unlink-packet    vFile:unlink            remote delete
+*/
 
 using namespace trk;
 
 enum { KnownRegisters = RegisterPSGdb + 1};
 
-#define CB(s) Callback(this, &Adapter::s)
-
 static const char *registerNames[KnownRegisters] =
 {
     "A1", "A2", "A3", "A4",
@@ -81,1529 +109,55 @@ static QByteArray dumpRegister(int n, uint value)
         ba += '#';
         ba += QByteArray::number(n);
     }
-    ba += "=0x" + hexNumber(value);
+    ba += "=" + hexxNumber(value);
     return ba;
 }
 
+
 ///////////////////////////////////////////////////////////////////////
 //
-// Adapter
+// RunnerGui
 //
 ///////////////////////////////////////////////////////////////////////
 
-class Adapter : public QObject
+class TextEdit : public QTextEdit
 {
     Q_OBJECT
 
-public:
-    typedef TrkFunctor1<const TrkResult &> Callback;
-
-    Adapter();
-    ~Adapter();
-    void setGdbServerName(const QString &name);
-    QString gdbServerIP() const;
-    uint gdbServerPort() const;
-    void setTrkServerName(const QString &name) { m_trkServerName = name; }
-    void setVerbose(int verbose) { m_verbose = verbose; }
-    void setSerialFrame(bool b) { m_serialFrame = b; }
-    void setRegisterEndianness(Endianness r) { m_registerEndianness = r; }
-    void setBufferedMemoryRead(bool b) { m_bufferedMemoryRead = b; }
-
-public slots:
-    void startServer();
-
-private slots:
-    void handleResult(const trk::TrkResult &data);
-
 signals:
-    void output(const QString &senderName, const QString &data);
-
-private slots:
-    void handleProcError(QProcess::ProcessError error);
-    void handleProcFinished(int exitCode, QProcess::ExitStatus exitStatus);
-    void handleProcReadyReadStandardError();
-    void handleProcReadyReadStandardOutput();
-    void handleProcStarted();
-    void handleProcStateChanged(QProcess::ProcessState newState);
-    void run();
-    void startGdb();
-    void writeToGdb(const QString &msg);
-
-private:
-    friend class RunnerGui;
-    void connectProcess(QProcess *proc);
-    void sendOutput(QObject *sender, const QString &data);
-    void sendOutput(const QString &data) { sendOutput(0, data); }
-
-    QString m_endianness;
-    QString m_trkServerName; // 
-    QString m_gdbServerName; // 127.0.0.1:(2222+uid)
-
-    QProcess m_gdbProc;
-    QProcess m_rfcommProc;
-
-public:
-    //
-    // TRK
-    //
-
-    bool openTrkPort(const QString &port, QString *errorMessage); // or server name for local server
-    void sendTrkMessage(byte code,
-        Callback callBack = Callback(),
-        const QByteArray &data = QByteArray(),
-        const QVariant &cookie = QVariant(),
-        bool invokeOnFailure = false);
-
-    // convenience messages
-    void sendTrkInitialPing();
-    void sendTrkContinue();
-    void waitForTrkFinished();
-    void sendTrkAck(byte token);
-
-    // kill process and breakpoints
-    void cleanUp();
-
-    void handleCpuType(const TrkResult &result);
-    void handleCreateProcess(const TrkResult &result);
-    void handleClearBreakpoint(const TrkResult &result);
-    void handleSignalContinue(const TrkResult &result);
-    void handleWaitForFinished(const TrkResult &result);
-    void handleStop(const TrkResult &result);
-    void handleSupportMask(const TrkResult &result);
-    void handleTrkVersions(const TrkResult &result);
-    void handleDisconnect(const TrkResult &result);
-
-    void handleAndReportCreateProcess(const TrkResult &result);
-    void handleAndReportReadRegisters(const TrkResult &result);
-    QByteArray memoryReadLogMessage(uint addr, uint len, const QByteArray &ba) const;
-    void handleAndReportSetBreakpoint(const TrkResult &result);
-    void handleReadMemoryBuffered(const TrkResult &result);
-    void handleReadMemoryUnbuffered(const TrkResult &result);
-    void handleStepRange(const TrkResult &result);
-    void reportReadMemoryBuffered(const TrkResult &result);
-    void reportToGdb(const TrkResult &result);
-
-    void clearTrkBreakpoint(const Breakpoint &bp);
-
-    void handleSetTrkBreakpoint(const TrkResult &result);
-    void setTrkBreakpoint(const Breakpoint &bp);
-
-    void readMemory(uint addr, uint len);
-    void startInferiorIfNeeded();
-    void interruptInferior();
-
-    TrkDevice m_trkDevice;
-
-    QList<Breakpoint> m_breakpoints;
-
-    //
-    // Gdb
-    //
-    Q_SLOT void handleGdbConnection();
-    Q_SLOT void readFromGdb();
-    void handleGdbResponse(const QByteArray &ba);
-    void sendGdbMessage(const QByteArray &msg,
-        const QByteArray &logNote = QByteArray());
-    void sendGdbMessageAfterSync(const QByteArray &msg,
-        const QByteArray &logNote = QByteArray());
-    void sendGdbAckMessage();
-    bool sendGdbPacket(const QByteArray &packet, bool doFlush);
-    void executeGdbCommand(const QString &msg);
-
-    void logMessage(const QString &msg, bool force = false);
-    Q_SLOT void trkLogMessage(const QString &msg);
-
-    QTcpServer m_gdbServer;
-    QPointer<QTcpSocket> m_gdbConnection;
-    QByteArray m_gdbReadBuffer;
-    bool m_gdbAckMode;
-
-    // Debuggee state
-    Session m_session; // global-ish data (process id, target information)
-    Snapshot m_snapshot; // local-ish data (memory and registers)
-    int m_verbose;
-    Endianness m_registerEndianness;
-    bool m_serialFrame;
-    bool m_startInferiorTriggered;
-    bool m_bufferedMemoryRead;
-};
-
-Adapter::Adapter()
-{
-    m_gdbAckMode = true;
-    m_verbose = 2;
-    m_registerEndianness = LittleEndian;
-    //m_serialFrame = true;
-    m_serialFrame = false;
-    m_startInferiorTriggered = false;
-    //m_bufferedMemoryRead = true;
-    m_bufferedMemoryRead = false;
-    // m_breakpoints.append(Breakpoint(0x0040)); // E32Main
-    m_breakpoints.append(Breakpoint(0x0cc8)); // E32Main
-    m_trkServerName = "/dev/rfcomm0";
-
-    m_endianness = "little";
-
-    uid_t userId = getuid();
-    m_gdbServerName = QString("127.0.0.1:%1").arg(2222 + userId);
-
-    m_gdbProc.setObjectName("GDB PROCESS");
-    connectProcess(&m_gdbProc);
-
-    m_rfcommProc.setObjectName("RFCOMM PROCESS");
-    connectProcess(&m_rfcommProc);
-
-    connect(&m_trkDevice, SIGNAL(logMessage(QString)),
-        this, SLOT(trkLogMessage(QString)));
-}
-
-Adapter::~Adapter()
-{
-    m_gdbServer.close();
-    logMessage("Shutting down.\n", true);
-}
-
-void Adapter::trkLogMessage(const QString &msg)
-{
-    logMessage("TRK " + msg);
-}
-
-void Adapter::setGdbServerName(const QString &name)
-{
-    m_gdbServerName = name;
-}
-
-QString Adapter::gdbServerIP() const
-{
-    int pos = m_gdbServerName.indexOf(':');
-    if (pos == -1)
-        return m_gdbServerName;
-    return m_gdbServerName.left(pos);
-}
-
-uint Adapter::gdbServerPort() const
-{
-    int pos = m_gdbServerName.indexOf(':');
-    if (pos == -1)
-        return 0;
-    return m_gdbServerName.mid(pos + 1).toUInt();
-}
-
-void Adapter::startServer()
-{
-    QString errorMessage;
-    if (!openTrkPort(m_trkServerName, &errorMessage)) {
-        logMessage(errorMessage, true);
-        logMessage("LOOPING");
-        QTimer::singleShot(1000, this, SLOT(startServer()));
-        return;
-    }
-
-    sendTrkInitialPing();
-    sendTrkMessage(0x01); // Connect
-    sendTrkMessage(0x05, CB(handleSupportMask));
-    sendTrkMessage(0x06, CB(handleCpuType));
-    sendTrkMessage(0x04, CB(handleTrkVersions)); // Versions
-    //sendTrkMessage(0x09); // Unrecognized command
-    //sendTrkMessage(0x4a, 0,
-    //    "10 " + formatString("C:\\data\\usingdlls.sisx")); // Open File
-    //sendTrkMessage(0x4B, 0, "00 00 00 01 73 1C 3A C8"); // Close File
-
-    logMessage("Connected to TRK server");
-
-    if (!m_gdbServer.listen(QHostAddress(gdbServerIP()), gdbServerPort())) {
-        logMessage(QString("Unable to start the gdb server at %1: %2.")
-            .arg(m_gdbServerName).arg(m_gdbServer.errorString()), true);
-        QCoreApplication::exit(5);
-        return;
-    }
-
-    logMessage(QString("Gdb server running on %1.\nRegister endianness: %3.")
-        .arg(m_gdbServerName).arg(m_registerEndianness), true);
-
-    connect(&m_gdbServer, SIGNAL(newConnection()),
-        this, SLOT(handleGdbConnection()));
-
-    startGdb();
-}
-
-void Adapter::logMessage(const QString &msg, bool force)
-{
-    if (m_verbose || force)
-        emit output(QString(), msg);
-}
-
-//
-// Gdb
-//
-void Adapter::handleGdbConnection()
-{
-    logMessage("HANDLING GDB CONNECTION");
-
-    m_gdbConnection = m_gdbServer.nextPendingConnection();
-    connect(m_gdbConnection, SIGNAL(disconnected()),
-            m_gdbConnection, SLOT(deleteLater()));
-    connect(m_gdbConnection, SIGNAL(readyRead()),
-            this, SLOT(readFromGdb()));
-    m_startInferiorTriggered = false;
-}
-
-static inline QString msgGdbPacket(const QString &p)
-{
-    return QLatin1String("gdb:                              ") + p;
-}
-
-void Adapter::readFromGdb()
-{
-    QByteArray packet = m_gdbConnection->readAll();
-    m_gdbReadBuffer.append(packet);
-
-    logMessage("gdb: -> " + QString::fromAscii(packet));
-    if (packet != m_gdbReadBuffer)
-        logMessage("buffer: " + m_gdbReadBuffer);
-
-    QByteArray &ba = m_gdbReadBuffer;
-    while (ba.size()) {
-        char code = ba.at(0);
-        ba = ba.mid(1);
-
-        if (code == '+') {
-            //logMessage("ACK");
-            continue;
-        }
-
-        if (code == '-') {
-            logMessage("NAK: Retransmission requested");
-            continue;
-        }
-
-        if (code == char(0x03)) {
-            logMessage("INTERRUPT RECEIVED");
-            interruptInferior();
-            continue;
-        }
-
-        if (code != '$') {
-            logMessage("Broken package (2) " + quoteUnprintableLatin1(ba)
-                + hexNumber(code));
-            continue;
-        }
-
-        int pos = ba.indexOf('#');
-        if (pos == -1) {
-            logMessage("Invalid checksum format in "
-                + quoteUnprintableLatin1(ba));
-            continue;
-        }
-
-        bool ok = false;
-        uint checkSum = ba.mid(pos + 1, 2).toUInt(&ok, 16);
-        if (!ok) {
-            logMessage("Invalid checksum format 2 in "
-                + quoteUnprintableLatin1(ba));
-            return;
-        }
-
-        //logMessage(QString("Packet checksum: %1").arg(checkSum));
-        byte sum = 0;
-        for (int i = 0; i < pos; ++i)
-            sum += ba.at(i);
-
-        if (sum != checkSum) {
-            logMessage(QString("ERROR: Packet checksum wrong: %1 %2 in "
-                + quoteUnprintableLatin1(ba)).arg(checkSum).arg(sum));
-        }
-
-        QByteArray response = ba.left(pos);
-        ba.remove(0, pos + 3);
-        handleGdbResponse(response);
-    }
-}
-
-bool Adapter::sendGdbPacket(const QByteArray &packet, bool doFlush)
-{
-    if (!m_gdbConnection || m_gdbConnection->state() != QAbstractSocket::ConnectedState) {
-        logMessage(QString::fromLatin1("Cannot write to gdb: Not connected (%1)").arg(QString::fromLatin1(packet)), true);
-        return false;
-    }
-    if (m_gdbConnection->write(packet) == -1) {
-        logMessage(QString::fromLatin1("Cannot write to gdb: %1 (%2)").arg(m_gdbConnection->errorString()).arg(QString::fromLatin1(packet)), true);
-        return false;
-    }
-    if (doFlush)
-        m_gdbConnection->flush();
-    return true;
-}
-
-void Adapter::sendGdbAckMessage()
-{
-    if (!m_gdbAckMode)
-        return;
-    QByteArray packet = "+";
-    logMessage("gdb: <- " + packet);
-    sendGdbPacket(packet, false);
-}
-
-void Adapter::sendGdbMessage(const QByteArray &msg, const QByteArray &logNote)
-{
-    byte sum = 0;
-    for (int i = 0; i != msg.size(); ++i)
-        sum += msg.at(i);
-
-    char checkSum[30];
-    qsnprintf(checkSum, sizeof(checkSum) - 1, "%02x ", sum);
-
-    //logMessage(QString("Packet checksum: %1").arg(sum));
-
-    QByteArray packet;
-    packet.append("$");
-    packet.append(msg);
-    packet.append('#');
-    packet.append(checkSum);
-    int pad = qMax(0, 24 - packet.size());
-    logMessage("gdb: <- " + packet + QByteArray(pad, ' ') + logNote);
-    sendGdbPacket(packet, true);
-}
-
-void Adapter::sendGdbMessageAfterSync(const QByteArray &msg, const QByteArray &logNote)
-{
-    QByteArray ba = msg + char(1) + logNote;
-    sendTrkMessage(TRK_WRITE_QUEUE_NOOP_CODE, CB(reportToGdb), "", ba); // Answer gdb
-}
-
-void Adapter::reportToGdb(const TrkResult &result)
-{
-    QByteArray message = result.cookie.toByteArray();
-    QByteArray note;
-    int pos = message.lastIndexOf(char(1)); // HACK
-    if (pos != -1) {
-        note = message.mid(pos + 1);
-        message = message.left(pos);
-    }
-    message.replace("@CODESEG@", hexNumber(m_session.codeseg));
-    message.replace("@DATASEG@", hexNumber(m_session.dataseg));
-    message.replace("@PID@", hexNumber(m_session.pid));
-    message.replace("@TID@", hexNumber(m_session.tid));
-    sendGdbMessage(message, note);
-}
-
-static QByteArray trkBreakpointMessage(uint addr, int len, int pid, bool armMode = true)
-{
-    QByteArray ba;
-    appendByte(&ba, 0x82);  // unused option
-    appendByte(&ba, armMode /*bp.mode == ArmMode*/ ? 0x00 : 0x01);
-    appendInt(&ba, addr);
-    appendInt(&ba, len);
-    appendInt(&ba, 0x00000001);
-    appendInt(&ba, pid);
-    appendInt(&ba, 0xFFFFFFFF);
-    return ba;
-}
-
-void Adapter::handleGdbResponse(const QByteArray &response)
-{
-    // http://sourceware.org/gdb/current/onlinedocs/gdb_34.html
-    if (0) {}
-
-    else if (response == "!") {
-        sendGdbAckMessage();
-        sendGdbMessage("", "extended mode not enabled");
-        //sendGdbMessage("OK", "extended mode enabled");
-    }
-
-    else if (response.startsWith("?")) {
-        if (m_verbose)
-            logMessage(msgGdbPacket(QLatin1String("Query halted")));
-        // Indicate the reason the target halted.
-        // The reply is the same as for step and continue.
-        sendGdbAckMessage();
-        startInferiorIfNeeded();        
-        sendGdbMessage("T05library:r;", "target halted (library load)");
-        // trap 05
-        // sendGdbMessage("S05", "target halted (trap)");
-    }
-
-    else if (response == "c") {
-        if (m_verbose)
-            logMessage(msgGdbPacket(QLatin1String("continue")));
-        sendGdbAckMessage();
-        QByteArray ba;
-        appendByte(&ba, 0); // options
-        appendInt(&ba, 0); // start address
-        appendInt(&ba, 0); // end address
-        appendInt(&ba, m_session.pid);
-        appendInt(&ba, m_session.tid);
-        sendTrkMessage(0x18, Callback(), ba);
-        // FIXME: should be triggered by real stop
-        //sendGdbMessageAfterSync("S11", "target stopped");
-    }
-
-    else if (response.startsWith("C")) {
-        if (m_verbose)
-            logMessage(msgGdbPacket(QLatin1String("continue with signal")));
-        // C sig[;addr] Continue with signal sig (hex signal number)
-        //Reply: See section D.3 Stop Reply Packets, for the reply specifications.
-        sendGdbAckMessage();
-        bool ok = false;
-        uint signalNumber = response.mid(1).toInt(&ok, 16);
-        QByteArray ba;
-        appendInt(&ba, m_session.pid);
-        appendInt(&ba, m_session.tid);
-        sendTrkMessage(0x18, CB(handleSignalContinue), ba, signalNumber); // Continue
-    }
-
-    else if (response.startsWith("D")) {
-        sendGdbAckMessage();
-        sendGdbMessage("OK", "shutting down");
-        qApp->quit();
-    }
-
-    else if (response == "g") {
-        if (m_verbose)
-            logMessage(msgGdbPacket(QLatin1String("read registers")));
-        // Read general registers.
-        //sendGdbMessage("00000000", "read registers");
-        sendGdbAckMessage();
-        QByteArray ba;
-        appendByte(&ba, 0); // Register set, only 0 supported
-        appendShort(&ba, 0);
-        appendShort(&ba, RegisterCount - 1); // last register
-        appendInt(&ba, m_session.pid);
-        appendInt(&ba, m_session.tid);
-        sendTrkMessage(0x12, CB(handleAndReportReadRegisters), ba, QVariant(), true);
-    }
-
-    else if (response.startsWith("Hc")) {
-        if (m_verbose)
-            logMessage(msgGdbPacket(QLatin1String("Set thread & continue")));
-        // Set thread for subsequent operations (`m', `M', `g', `G', et.al.).
-        // for step and continue operations
-        //$Hc-1#09
-        sendGdbAckMessage();
-        sendGdbMessage("OK", "Set current thread for step & continue");
-    }
-
-    else if (response.startsWith("Hg")) {
-        if (m_verbose)
-            logMessage(msgGdbPacket(QLatin1String("Set thread")));
-        // Set thread for subsequent operations (`m', `M', `g', `G', et.al.).
-        // for 'other operations.  0 - any thread
-        //$Hg0#df
-        sendGdbAckMessage();
-        m_session.currentThread = response.mid(2).toInt(0, 16);
-        sendGdbMessage("OK", "Set current thread "
-            + QByteArray::number(m_session.currentThread));
-    }
-
-    else if (response == "k") {
-        if (m_verbose)
-            logMessage(msgGdbPacket(QLatin1String("kill")));
-        // kill
-        sendGdbAckMessage();
-        QByteArray ba;
-        appendByte(&ba, 0); // Sub-command: Delete Process
-        appendInt(&ba, m_session.pid);
-        sendTrkMessage(0x41, Callback(), ba, "Delete process"); // Delete Item
-        sendGdbMessageAfterSync("", "process killed");
-    }
+    void executeCommand(QString);
 
-    else if (response.startsWith("m")) {
-        if (m_verbose)
-            logMessage(msgGdbPacket(QLatin1String("read memory")));
-        // m addr,length
-        sendGdbAckMessage();
-        uint addr = 0, len = 0;
-        do {
-            const int pos = response.indexOf(',');
-            if (pos == -1)
-                break;
-            bool ok;
-            addr = response.mid(1, pos - 1).toUInt(&ok, 16);
-            if (!ok)
-                break;
-            len = response.mid(pos + 1).toUInt(&ok, 16);
-            if (!ok)
-                break;
-        } while (false);
-        if (len) {
-            readMemory(addr, len);
-        } else {
-            sendGdbMessage("E20", "Error " + response);
-        }
-    }
-    else if (response.startsWith("p")) {
-        if (m_verbose)
-            logMessage(msgGdbPacket(QLatin1String("read register")));
-        // 0xf == current instruction pointer?
-        //sendGdbMessage("0000", "current IP");
-        sendGdbAckMessage();
-        #if 0
-          A1 = 0,	 first integer-like argument
-          A4 = 3,	 last integer-like argument
-          AP = 11,
-          IP = 12,
-          SP = 13,	 Contains address of top of stack
-          LR = 14,	 address to return to from a function call
-          PC = 15,	 Contains program counter
-          F0 = 16,	 first floating point register
-          F3 = 19,	 last floating point argument register
-          F7 = 23, 	 last floating point register
-          FPS = 24,	 floating point status register
-          PS = 25,	 Contains processor status
-          WR0,		 WMMX data registers.
-          WR15 = WR0 + 15,
-          WC0,		 WMMX control registers.
-          WCSSF = WC0 + 2,
-          WCASF = WC0 + 3,
-          WC7 = WC0 + 7,
-          WCGR0,		WMMX general purpose registers.
-          WCGR3 = WCGR0 + 3,
-          WCGR7 = WCGR0 + 7,
-          NUM_REGS,
-
-          // Other useful registers.
-          FP = 11,		Frame register in ARM code, if used.
-          THUMB_FP = 7,		Frame register in Thumb code, if used.
-          NUM_ARG_REGS = 4,
-          LAST_ARG = A4,
-          NUM_FP_ARG_REGS = 4,
-          LAST_FP_ARG = F3
-        #endif
-        bool ok = false;
-        const uint registerNumber = response.mid(1).toInt(&ok, 16);
-        QByteArray logMsg = "Read Register";
-        if (registerNumber == RegisterPSGdb) {
-            QByteArray ba;
-            appendInt(&ba, m_snapshot.registers[RegisterPSTrk], m_registerEndianness);
-            logMsg += dumpRegister(registerNumber, m_snapshot.registers[RegisterPSTrk]);
-            sendGdbMessage(ba.toHex(), logMsg);
-        } else if (registerNumber < RegisterCount) {
-            QByteArray ba;
-            appendInt(&ba, m_snapshot.registers[registerNumber], m_registerEndianness);
-            logMsg += dumpRegister(registerNumber, m_snapshot.registers[registerNumber]);
-            sendGdbMessage(ba.toHex(), logMsg);
-        } else {
-            sendGdbMessage("0000", "read single unknown register #" + QByteArray::number(registerNumber));
-            //sendGdbMessage("E01", "read single unknown register");
-        }
-    }
-
-    else if (response == "qAttached") {
-        //$qAttached#8f
-        // 1: attached to an existing process
-        // 0: created a new process
-        sendGdbAckMessage();
-        sendGdbMessage("0", "new process created");
-        //sendGdbMessage("1", "attached to existing process");
-        //sendGdbMessage("E01", "new process created");
-    }
-
-    else if (response.startsWith("qC")) {
-        if (m_verbose)
-            logMessage(msgGdbPacket(QLatin1String("query thread id")));
-        // Return the current thread ID
-        //$qC#b4
-        sendGdbAckMessage();
-        startInferiorIfNeeded();
-        sendGdbMessageAfterSync("QC@TID@");
-    }
-
-    else if (response.startsWith("qSupported")) {
-        //$qSupported#37
-        //$qSupported:multiprocess+#c6
-        //logMessage("Handling 'qSupported'");
-        sendGdbAckMessage();
-        if (0)
-            sendGdbMessage(QByteArray(), "nothing supported");
-        else
-            sendGdbMessage(
-                "PacketSize=7cf;"
-                //"QPassSignals+;"
-                "qXfer:libraries:read+;"
-                //"qXfer:auxv:read+;"
-                "qXfer:features:read+");
-    }
-
-    else if (response == "qPacketInfo") {
-        // happens with  gdb 6.4.50.20060226-cvs / CodeSourcery
-        // deprecated by qSupported?
-        sendGdbAckMessage();
-        sendGdbMessage("", "FIXME: nothing?");
-    }
-
-    else if (response == "qOffsets") {
-        sendGdbAckMessage();
-        startInferiorIfNeeded();
-        sendGdbMessageAfterSync("TextSeg=@CODESEG@;DataSeg=@DATASEG@");
+public slots:
+    void handleOutput(const QString &senderName, const QString &data)
+    {
+        QString str = senderName + data;
+        str.replace("\\t", QString(QChar(0x09)));
+        str.replace("\\n", QString("\n"));
+        append(str);
+
+        QTextCursor tc = textCursor();
+        tc.movePosition(QTextCursor::End);
+        setTextCursor(tc);
+    /*
+        int pos1 = str.indexOf("#");
+        int pos2 = str.indexOf(")", pos1);
+        if (pos1 != -1 && pos2 != -1)
+            str = str.left(pos1) + "<b>" + str.mid(pos1, pos2 - pos1 + 1)
+                + "</b> " + str.mid(pos2 + 1);
+        insertHtml(str + "\n");
+    */
+        setCurrentCharFormat(QTextCharFormat());
+        ensureCursorVisible();
     }
 
-    else if (response == "qSymbol::") {
-        if (m_verbose)
-            logMessage(msgGdbPacket(QLatin1String("notify can handle symbol lookup")));
-        // Notify the target that GDB is prepared to serve symbol lookup requests.
-        sendGdbAckMessage();
-        if (1)
-            sendGdbMessage("OK", "no further symbols needed");
+    void keyPressEvent(QKeyEvent *ev)
+    {
+        if (ev->modifiers() == Qt::ControlModifier && ev->key() == Qt::Key_Return)
+            emit executeCommand(textCursor().block().text());
         else
-            sendGdbMessage("qSymbol:" + QByteArray("_Z7E32Mainv").toHex(), "ask for more");
-    }
-
-    else if (response.startsWith("qXfer:features:read:target.xml:")) {
-        //  $qXfer:features:read:target.xml:0,7ca#46...Ack
-        sendGdbAckMessage();
-        sendGdbMessage("l<target><architecture>symbianelf</architecture></target>");
-    }
-
-    else if (response == "QStartNoAckMode") {
-        //$qSupported#37
-        //logMessage("Handling 'QStartNoAckMode'");
-        sendGdbAckMessage();
-        sendGdbMessage("OK", "ack no-ack mode");
-        m_gdbAckMode = false;
-    }
-
-    else if (response.startsWith("QPassSignals")) {
-        // list of signals to pass directly to inferior
-        // $QPassSignals:e;10;14;17;1a;1b;1c;21;24;25;4c;#8f
-        // happens only if "QPassSignals+;" is qSupported
-        sendGdbAckMessage();
-        // FIXME: use the parameters
-        sendGdbMessage("OK", "passing signals accepted");
-    }
-
-    else if (response == "s") {
-        if (m_verbose)
-            logMessage(msgGdbPacket(QLatin1String("Step range")));
-        sendGdbAckMessage();
-        QByteArray ba;
-        appendByte(&ba, 0); // options
-        appendInt(&ba, m_snapshot.registers[RegisterPC]); // start address
-        appendInt(&ba, m_snapshot.registers[RegisterPC] + 4); // end address
-        appendInt(&ba, m_session.pid);
-        appendInt(&ba, m_session.tid);
-        sendTrkMessage(0x19, CB(handleStepRange), ba, "Step range");
-        // FIXME: should be triggered by "real" stop"
-        //sendGdbMessageAfterSync("S05", "target halted");
-    }
-
-    else if (response == "vCont?") {
-        // actions supported by the vCont packet
-        sendGdbAckMessage();
-        sendGdbMessage(""); // we don't support vCont.
-        //sendGdbMessage("vCont;c");
-    }
-
-    //else if (response.startsWith("vCont")) {
-    //    // vCont[;action[:thread-id]]...'
-    //}
-
-    else if (response.startsWith("vKill")) {
-        // kill
-        sendGdbAckMessage();
-        QByteArray ba;
-        appendByte(&ba, 0); // Sub-command: Delete Process
-        appendInt(&ba, m_session.pid);
-        sendTrkMessage(0x41, Callback(), ba, "Delete process"); // Delete Item
-        sendGdbMessageAfterSync("", "process killed");
-    }
-
-    else if (response.startsWith("Z0,")) { // Insert breakpoint
-        if (m_verbose)
-            logMessage(msgGdbPacket(QLatin1String("Insert breakpoint")));
-        // $z0,786a4ccc,4#99
-        const int pos = response.lastIndexOf(',');
-        bool ok = false;
-        const uint addr = response.mid(3, pos - 1).toInt(&ok, 16);
-        const uint len = response.mid(pos + 1).toInt(&ok, 16);
-        if (m_verbose)
-            logMessage(QString::fromLatin1("Inserting breakpoint at 0x%1, %2").arg(addr,0 ,16).arg(len));
-
-        //---IDE------------------------------------------------------
-        //  Command: 0x1B Set Break
-        //BreakType: 0x82
-        //  Options: 0x00
-        //  Address: 0x78674340 (2020033344)    i.e + 0x00000340
-        //   Length: 0x00000001 (1)
-        //    Count: 0x00000000 (0)
-        //ProcessID: 0x000001b5 (437)
-        // ThreadID: 0xffffffff (-1)
-        // [1B 09 82 00 78 67 43 40 00 00 00 01 00 00 00 00
-        //  00 00 01 B5 FF FF FF FF]
-        const QByteArray ba = trkBreakpointMessage(addr, len, m_session.pid);
-        sendTrkMessage(0x1B, CB(handleAndReportSetBreakpoint), ba);
-        //m_session.toekn
-
-        //---TRK------------------------------------------------------
-        //  Command: 0x80 Acknowledge
-        //    Error: 0x00
-        // [80 09 00 00 00 00 0A]
-    } else if (response.startsWith("qPart:") || response.startsWith("qXfer:"))  {
-        QByteArray data  = response.mid(1 + response.indexOf(':'));
-        // "qPart:auxv:read::0,147": Read OS auxiliary data (see info aux)
-        bool handled = false;
-        if (data.startsWith("auxv:read::")) {
-            const int offsetPos = data.lastIndexOf(':') + 1;
-            const int commaPos = data.lastIndexOf(',');
-            if (commaPos != -1) {                
-                bool ok1 = false, ok2 = false;
-                const int offset = data.mid(offsetPos,  commaPos - offsetPos).toInt(&ok1, 16);
-                const int length = data.mid(commaPos + 1).toInt(&ok2, 16);
-                if (ok1 && ok2) {
-                    const QString msg = QString::fromLatin1("Read of OS auxilary vector (%1, %2) not implemented.").arg(offset).arg(length);
-                    logMessage(msgGdbPacket(msg), true);
-                    sendGdbMessage("E20", msg.toLatin1());
-                    handled = true;
-                }
-            }
-        } // auxv read
-        if (!handled) {
-            const QString msg = QLatin1String("FIXME unknown 'XFER'-request: ") + QString::fromAscii(response);
-            logMessage(msgGdbPacket(msg), true);
-            sendGdbMessage("E20", msg.toLatin1());
-        }
-    } // qPart/qXfer
-    else {
-        logMessage(msgGdbPacket(QLatin1String("FIXME unknown: ") + QString::fromAscii(response)));
-    }
-}
-
-void Adapter::executeGdbCommand(const QString &msg)
-{
-    logMessage("EXECUTING GDB COMMAND " + msg);
-    if (msg == "S")
-        writeToGdb("-exec-interrupt");
-    if (msg == "I")
-        interruptInferior();
-    else
-        writeToGdb(msg);
-}
-
-bool Adapter::openTrkPort(const QString &port, QString *errorMessage)
-{
-    connect(&m_trkDevice, SIGNAL(messageReceived(trk::TrkResult)),
-        this, SLOT(handleResult(trk::TrkResult)));
-    if (m_verbose > 1)
-        m_trkDevice.setVerbose(true);
-    m_trkDevice.setSerialFrame(m_serialFrame);
-    return m_trkDevice.open(port, errorMessage);
-}
-
-void Adapter::sendTrkMessage(byte code, Callback callBack,
-    const QByteArray &data, const QVariant &cookie, bool invokeOnFailure)
-{
-    m_trkDevice.sendTrkMessage(code, callBack, data, cookie, invokeOnFailure);
-}
-
-void Adapter::sendTrkInitialPing()
-{
-    m_trkDevice.sendTrkInitialPing();
-}
-
-void Adapter::sendTrkContinue()
-{
-    QByteArray ba;
-    appendInt(&ba, m_session.pid);
-    appendInt(&ba, m_session.tid);
-    sendTrkMessage(0x18, Callback(), ba, "CONTINUE");
-}
-
-void Adapter::waitForTrkFinished()
-{
-    // initiate one last roundtrip to ensure all is flushed
-    sendTrkMessage(0x0, CB(handleWaitForFinished));
-}
-
-void Adapter::sendTrkAck(byte token)
-{
-    logMessage(QString("SENDING ACKNOWLEDGEMENT FOR TOKEN %1").arg(int(token)));
-    m_trkDevice.sendTrkAck(token);
-}
-
-void Adapter::handleResult(const TrkResult &result)
-{
-    if (result.isDebugOutput) {
-        logMessage(QLatin1String("APPLICATION OUTPUT: ") + QString::fromAscii(result.data));
-        return;
-    }
-    QByteArray prefix = "READ BUF:                                       ";
-    QByteArray str = result.toString().toUtf8();
-    switch (result.code) {
-        case 0x80: // ACK
-            break;
-        case 0xff: { // NAK. This mostly means transmission error, not command failed.
-            QString logMsg;
-            QTextStream(&logMsg) << prefix << "NAK: for token=" << result.token << " ERROR: " << errorMessage(result.data.at(0)) << ' ' << str;
-            logMessage(logMsg, true);
-            break;
-        }
-        case 0x90: { // Notified Stopped
-            // 90 01   78 6a 40 40   00 00 07 23   00 00 07 24  00 00
-            const char *data = result.data.data();
-            const uint addr = extractInt(data); //code address: 4 bytes; code base address for the library
-            const uint pid = extractInt(data + 4); // ProcessID: 4 bytes;
-            const uint tid = extractInt(data + 8); // ThreadID: 4 bytes
-            logMessage(prefix + QString::fromLatin1("NOTE: PID %1/TID %2 "
-                "STOPPED at 0x%3").arg(pid).arg(tid).arg(addr, 0, 16));
-            sendTrkAck(result.token);
-            if (addr) {
-                // Todo: Do not send off GdbMessages if a synced gdb
-                // query is pending, queue instead
-                //sendGdbMessage("S05", "Target stopped");
-            } else {
-                if (m_verbose)
-                    logMessage(QLatin1String("Ignoring stop at 0"));
-            }
-            break;
-        }
-        case 0x91: { // Notify Exception (obsolete)
-            logMessage(prefix + "NOTE: EXCEPTION  " + str);
-            sendTrkAck(result.token);
-            break;
-        }
-        case 0x92: { //
-            logMessage(prefix + "NOTE: INTERNAL ERROR: " + str);
-            sendTrkAck(result.token);
-            break;
-        }
-
-        // target->host OS notification
-        case 0xa0: { // Notify Created
-            const char *data = result.data.data();
-            const byte error = result.data.at(0);
-            const byte type = result.data.at(1); // type: 1 byte; for dll item, this value is 2.
-            const uint pid = extractInt(data + 2); //  ProcessID: 4 bytes;
-            const uint tid = extractInt(data + 6); //threadID: 4 bytes
-            const uint codeseg = extractInt(data + 10); //code address: 4 bytes; code base address for the library
-            const uint dataseg = extractInt(data + 14); //data address: 4 bytes; data base address for the library
-            const uint len = extractShort(data + 18); //length: 2 bytes; length of the library name string to follow
-            const QByteArray name = result.data.mid(20, len); // name: library name
-            m_session.modules += QString::fromAscii(name);
-            QString logMsg;
-            QTextStream str(&logMsg);
-            str<< prefix << " NOTE: LIBRARY LOAD: token=" << result.token;
-            if (error)
-                str<< " ERROR: " << int(error);
-            str << " TYPE: " << int(type) << " PID: " << pid << " TID:   " <<  tid;
-            str.setIntegerBase(16);
-            str << " CODE: 0x" << codeseg << " DATA: 0x" << dataseg;
-            str.setIntegerBase(10);
-            str << " NAME: '" << name << '\'';
-            logMessage(logMsg);
-            sendTrkContinue();
-            break;
-        }
-        case 0xa1: { // NotifyDeleted
-            const ushort itemType = (unsigned char)result.data.at(1);
-            const ushort len = result.data.size() > 12 ? extractShort(result.data.data() + 10) : ushort(0);
-            const QString name = len ? QString::fromAscii(result.data.mid(12, len)) : QString();
-            if (!name.isEmpty())
-                m_session.modules.removeAll(name);
-            logMessage(QString::fromLatin1("%1 %2 UNLOAD: %3")
-                .arg(QString::fromAscii(prefix))
-                .arg(itemType ? QLatin1String("LIB") : QLatin1String("PROCESS"))
-                .arg(name));
-            sendTrkAck(result.token);
-            break;
-        }
-        case 0xa2: { // NotifyProcessorStarted
-            logMessage(prefix + "NOTE: PROCESSOR STARTED: " + str);
-            sendTrkAck(result.token);
-            break;
-        }
-        case 0xa6: { // NotifyProcessorStandby
-            logMessage(prefix + "NOTE: PROCESSOR STANDBY: " + str);
-            sendTrkAck(result.token);
-            break;
-        }
-        case 0xa7: { // NotifyProcessorReset
-            logMessage(prefix + "NOTE: PROCESSOR RESET: " + str);
-            sendTrkAck(result.token);
-            break;
-        }
-        default: {
-            logMessage(prefix + "INVALID: " + str);
-            break;
-        }
-    }
-}
-
-void Adapter::handleCpuType(const TrkResult &result)
-{
-    //---TRK------------------------------------------------------
-    //  Command: 0x80 Acknowledge
-    //    Error: 0x00
-    // [80 03 00  04 00 00 04 00 00 00]
-    m_session.cpuMajor = result.data[1];
-    m_session.cpuMinor = result.data[2];
-    m_session.bigEndian = result.data[3];
-    m_session.defaultTypeSize = result.data[4];
-    m_session.fpTypeSize = result.data[5];
-    m_session.extended1TypeSize = result.data[6];
-    //m_session.extended2TypeSize = result.data[6];
-    QString logMsg;
-    QTextStream(&logMsg) << "HANDLE CPU TYPE: CPU=" << m_session.cpuMajor << '.'
-        << m_session.cpuMinor << " bigEndian=" << m_session.bigEndian
-        << " defaultTypeSize=" << m_session.defaultTypeSize
-        << " fpTypeSize=" << m_session.fpTypeSize
-        << " extended1TypeSize=" <<  m_session.extended1TypeSize;
-    logMessage(logMsg);
-}
-
-void Adapter::setTrkBreakpoint(const Breakpoint &bp)
-{
-    //---IDE------------------------------------------------------
-    //  Command: 0x1B Set Break
-    //BreakType: 0x82
-    //  Options: 0x00
-    //  Address: 0x78674340 (2020033344)    i.e + 0x00000340
-    //   Length: 0x00000001 (1)
-    //    Count: 0x00000000 (0)
-    //ProcessID: 0x000001b5 (437)
-    // ThreadID: 0xffffffff (-1)
-    // [1B 09 82 00 78 67 43 40 00 00 00 01 00 00 00 00
-    //  00 00 01 B5 FF FF FF FF]
-    const QByteArray ba = trkBreakpointMessage(m_session.codeseg + bp.offset, 1, m_session.pid);
-    sendTrkMessage(0x1B, CB(handleSetTrkBreakpoint), ba);
-
-    //---TRK------------------------------------------------------
-    //  Command: 0x80 Acknowledge
-    //    Error: 0x00
-    // [80 09 00 00 00 00 0A]
-}
-
-void Adapter::handleSetTrkBreakpoint(const TrkResult &result)
-{
-    //---TRK------------------------------------------------------
-    //  Command: 0x80 Acknowledge
-    //    Error: 0x00
-    // [80 09 00 00 00 00 0A]
-    const  uint bpnr = extractInt(result.data.data());
-    if (m_verbose)
-        logMessage(QString::fromLatin1("SET BREAKPOINT %1 %2").arg(bpnr).arg(stringFromArray(result.data.data())));
-}
-
-void Adapter::handleCreateProcess(const TrkResult &result)
-{
-    //  40 00 00]
-    //logMessage("       RESULT: " + result.toString());
-    // [80 08 00   00 00 01 B5   00 00 01 B6   78 67 40 00   00 40 00 00]
-    const char *data = result.data.data();
-    m_session.pid = extractInt(data + 1);
-    m_session.tid = extractInt(data + 5);
-    m_session.codeseg = extractInt(data + 9);
-    m_session.dataseg = extractInt(data + 13);
-
-    logMessage("PID: 0x" + hexNumber(m_session.pid));
-    logMessage("TID: 0x" + hexNumber(m_session.tid));
-    logMessage("COD: 0x" + hexNumber(m_session.codeseg));
-    logMessage("DAT: 0x" + hexNumber(m_session.dataseg));
-
-    writeToGdb("add-symbol-file filebrowseapp.sym 0x"
-        + hexNumber(m_session.codeseg));
-    writeToGdb("symbol-file filebrowseapp.sym");
-
-    foreach (const Breakpoint &bp, m_breakpoints)
-        setTrkBreakpoint(bp);
-
-    sendTrkContinue();
-
-#if 0
-    //setTrkBreakpoint(0x0000, ArmMode);
-    //clearTrkBreakpoint(0x0000);
-
-#if 1
-    //---IDE------------------------------------------------------
-    //  Command: 0x42 Read Info
-    //          [42 0C 00 06 00 00 00 00 00 14 50 6F 6C 79 6D 6F
-    //  72 70 68 69 63 44 4C 4C 32 2E 64 6C 6C 00]
-    sendTrkMessage(0x42, CB(handleReadInfo),
-        "00 06 00 00 00 00 00 14 50 6F 6C 79 6D 6F "
-        "72 70 68 69 63 44 4C 4C 32 2E 64 6C 6C 00");
-    //sendTrkMessage(0x42, CB(handleReadInfo),
-    //        "00 01 00 00 00 00");
-    //---TRK------------------------------------------------------
-    //  Command: 0x80 Acknowledge
-    //    Error: 0x20 Unspecified general OS-related error
-    // [80 0C 20]
-
-
-    //---IDE------------------------------------------------------
-    //  Command: 0x42 Read Info
-    // [42 0D 00 06 00 00 00 00 00 14 50 6F 6C 79 6D 6F
-    //  72 70 68 69 63 44 4C 4C 31 2E 64 6C 6C 00]
-    sendTrkMessage(0x42, CB(handleReadInfo),
-        "00 06 00 00 00 00 00 14 50 6F 6C 79 6D 6F "
-        "72 70 68 69 63 44 4C 4C 31 2E 64 6C 6C 00");
-    //---TRK------------------------------------------------------
-    //  Command: 0x80 Acknowledge
-    //    Error: 0x20 Unspecified general OS-related error
-    // [80 0D 20]
-#endif
-
-    //sendTrkMessage(0x18, CB(handleStop),
-    //    "01 " + formatInt(m_session.pid) + formatInt(m_session.tid));
-
-    //---IDE------------------------------------------------------
-    //  Command: 0x18 Continue
-    //ProcessID: 0x000001B5 (437)
-    // ThreadID: 0x000001B6 (438)
-    // [18 0E 00 00 01 B5 00 00 01 B6]
-    QByteArray ba;
-    appendInt(&ba, m_session.pid);
-    appendInt(&ba, m_session.tid);
-    sendTrkMessage(0x18, CB(handleContinue), ba);
-    //sendTrkMessage(0x18, CB(handleContinue),
-    //    formatInt(m_session.pid) + "ff ff ff ff");
-    //---TRK------------------------------------------------------
-    //  Command: 0x80 Acknowledge
-    //    Error: 0x00
-    // [80 0E 00]
-#endif
-}
-
-void Adapter::handleAndReportReadRegisters(const TrkResult &result)
-{
-    logMessage("       RESULT: " + result.toString());
-    // [80 0B 00   00 00 00 00   C9 24 FF BC   00 00 00 00   00
-    //  60 00 00   00 00 00 00   78 67 79 70   00 00 00 00   00...]
-
-    const char *data = result.data.data() + 1; // Skip ok byte
-    for (int i = 0; i < RegisterCount; ++i) {
-        m_snapshot.registers[i] = extractInt(data + 4 * i);
-    }
-    QByteArray ba;
-    for (int i = 0; i < 16; ++i) {
-        const uint reg = m_registerEndianness == LittleEndian
-            ? swapEndian(m_snapshot.registers[i]) : m_snapshot.registers[i];
-        ba += hexNumber(reg, 8);
-    }
-    QByteArray logMsg = "REGISTER CONTENTS: ";
-    if (m_verbose > 1) {
-        for (int i = 0; i < RegisterCount; ++i) {
-            logMsg += dumpRegister(i, m_snapshot.registers[i]);
-            logMsg += ' ';
-        }
-    }
-    sendGdbMessage(ba, logMsg);
-}
-
-static inline QString msgMemoryReadError(int code, uint addr, uint len = 0)
-{
-    const QString lenS = len ? QString::number(len) : QLatin1String("<unknown>");
-    return QString::fromLatin1("Memory read error %1 at: 0x%2 %3").arg(code).arg(addr, 0 ,16).arg(lenS);
-}
-
-void Adapter::handleReadMemoryBuffered(const TrkResult &result)
-{
-    const uint blockaddr = result.cookie.toUInt();
-    if (const int errorCode = result.errorCode()) {
-        logMessage(msgMemoryReadError(errorCode, blockaddr));
-        return;
-    }
-    const QByteArray ba = result.data.mid(1);
-    m_snapshot.memory.insert(blockaddr , ba);
-}
-
-// Format log message for memory access with some smartness about registers
-QByteArray Adapter::memoryReadLogMessage(uint addr, uint len, const QByteArray &ba) const
-{
-    QByteArray logMsg = "memory contents";
-    if (m_verbose > 1) {
-        logMsg += " addr: 0x";
-        logMsg += QByteArray::number(addr, 16);
-        // indicate dereferencing of registers
-        if (len == 4) {
-            if (addr == m_snapshot.registers[RegisterPC]) {
-                logMsg += "[PC]";
-            } else if (addr == m_snapshot.registers[RegisterPSTrk]) {
-                logMsg += "[PSTrk]";
-            } else if (addr == m_snapshot.registers[RegisterSP]) {
-                logMsg += "[SP]";
-            } else if (addr == m_snapshot.registers[RegisterLR]) {
-                logMsg += "[LR]";
-            } else if (addr > m_snapshot.registers[RegisterSP] &&
-                    (addr - m_snapshot.registers[RegisterSP]) < 10240) {
-                logMsg += "[SP+"; // Stack area ...stack seems to be top-down
-                logMsg += QByteArray::number(addr - m_snapshot.registers[RegisterSP]);
-                logMsg += ']';
-            }
-        }
-        logMsg += " length ";
-        logMsg += QByteArray::number(len);
-        logMsg += " :";
-        logMsg += stringFromArray(ba, 16);
-    }
-    return logMsg;
-}
-
-void Adapter::reportReadMemoryBuffered(const TrkResult &result)
-{
-    const qulonglong cookie = result.cookie.toULongLong();
-    const uint addr = cookie >> 32;
-    const uint len = uint(cookie);
-
-    // Gdb accepts less memory according to documentation.
-    // Send E on complete failure.
-    QByteArray ba;
-    uint blockaddr = (addr / MemoryChunkSize) * MemoryChunkSize;
-    for (; blockaddr < addr + len; blockaddr += MemoryChunkSize) {
-        const Snapshot::Memory::const_iterator it = m_snapshot.memory.constFind(blockaddr);
-        if (it == m_snapshot.memory.constEnd())
-            break;
-        ba.append(it.value());
-    }
-    const int previousChunkOverlap = addr % MemoryChunkSize;
-    if (previousChunkOverlap != 0 && ba.size() > previousChunkOverlap)
-        ba.remove(0, previousChunkOverlap);
-    if (ba.size() > int(len))
-        ba.truncate(len);
-
-    if (ba.isEmpty()) {
-        ba = "E20";
-        sendGdbMessage(ba, msgMemoryReadError(32, addr, len).toLatin1());
-    } else {
-        sendGdbMessage(ba.toHex(), memoryReadLogMessage(addr, len, ba));
-    }
-}
-
-void Adapter::handleReadMemoryUnbuffered(const TrkResult &result)
-{
-    //logMessage("UNBUFFERED MEMORY READ: " + stringFromArray(result.data));
-    const uint blockaddr = result.cookie.toUInt();
-    if (extractShort(result.data.data() + 1) + 3 != result.data.size()) {
-        logMessage("\n BAD MEMORY RESULT: " + result.data.toHex() + "\n");
-    }
-    if (const int errorCode = result.errorCode()) {
-        const QByteArray ba = "E20";
-        sendGdbMessage(ba, msgMemoryReadError(32, blockaddr).toLatin1());
-    } else {
-        const QByteArray ba = result.data.mid(3);
-        sendGdbMessage(ba.toHex(), memoryReadLogMessage(blockaddr, ba.size(), ba));
-    }
-}
-
-void Adapter::handleStepRange(const TrkResult &result)
-{
-    // [80 0f 12]
-    //uint bpnr = extractInt(result.data.data());
-    logMessage("STEPPING FINISHED " + stringFromArray(result.data.data()));
-    sendGdbMessage("S05", "Stepping finished");
-}
-
-void Adapter::handleAndReportSetBreakpoint(const TrkResult &result)
-{
-    //---TRK------------------------------------------------------
-    //  Command: 0x80 Acknowledge
-    //    Error: 0x00
-    // [80 09 00 00 00 00 0A]
-    uint bpnr = extractInt(result.data.data());
-    logMessage("SET BREAKPOINT " + bpnr + stringFromArray(result.data.data()));
-    sendGdbMessage("OK");
-}
-
-void Adapter::clearTrkBreakpoint(const Breakpoint &bp)
-{
-    //---IDE------------------------------------------------------
-    //  Command: 0x1C Clear Break
-    // [1C 25 00 00 00 0A 78 6A 43 40]
-    QByteArray ba;
-    appendByte(&ba, 0x00);
-    appendShort(&ba, bp.number);
-    appendInt(&ba, m_session.codeseg + bp.offset);
-    sendTrkMessage(0x1C, CB(handleClearBreakpoint), ba);
-}
-
-void Adapter::handleClearBreakpoint(const TrkResult &result)
-{
-    Q_UNUSED(result);
-    //---TRK------------------------------------------------------
-    //  Command: 0x80 Acknowledge
-    //    Error: 0x00
-    // [80 09 00 00 00 00 0A]
-    logMessage("CLEAR BREAKPOINT ");
-}
-
-void Adapter::handleSignalContinue(const TrkResult &result)
-{
-    int signalNumber = result.cookie.toInt();
-    logMessage("   HANDLE SIGNAL CONTINUE: " + stringFromArray(result.data));
-    logMessage("NUMBER" + QString::number(signalNumber));
-    sendGdbMessage("O" + QByteArray("Console output").toHex());
-    sendGdbMessage("W81"); // "Process exited with result 1
-}
-
-void Adapter::handleWaitForFinished(const TrkResult &result)
-{
-    logMessage("   FINISHED: " + stringFromArray(result.data));
-    //qApp->exit(1);
-}
-
-void Adapter::handleSupportMask(const TrkResult &result)
-{
-    const char *data = result.data.data();
-    QByteArray str;
-    for (int i = 0; i < 32; ++i) {
-        //str.append("  [" + formatByte(data[i]) + "]: ");
-        for (int j = 0; j < 8; ++j)
-        if (data[i] & (1 << j))
-            str.append(QByteArray::number(i * 8 + j, 16));
-    }
-    logMessage("SUPPORTED: " + str);
- }
-
-void Adapter::handleTrkVersions(const TrkResult &result)
-{
-    QString logMsg;
-    QTextStream str(&logMsg);
-    str << "Versions: ";
-    if (result.data.size() >= 5) {
-        str << "Trk version " << int(result.data.at(1)) << '.'
-            << int(result.data.at(2))
-            << ", Protocol version " << int(result.data.at(3))
-             << '.' << int(result.data.at(4));
+            QTextEdit::keyPressEvent(ev);
     }
-    logMessage(logMsg);
-}
-
-void Adapter::handleDisconnect(const TrkResult & /*result*/)
-{
-    logMessage(QLatin1String("Trk disconnected"), true);
-}
-
-void Adapter::cleanUp()
-{
-    //
-    //---IDE------------------------------------------------------
-    //  Command: 0x41 Delete Item
-    //  Sub Cmd: Delete Process
-    //ProcessID: 0x0000071F (1823)
-    // [41 24 00 00 00 00 07 1F]
-    logMessage(QString::fromLatin1("Cleanup PID=%1").arg(m_session.pid), true);
-    if (!m_session.pid)
-        return;
-
-    QByteArray ba;
-    appendByte(&ba, 0x00);
-    appendByte(&ba, 0x00);
-    appendInt(&ba, m_session.pid);
-    sendTrkMessage(0x41, Callback(), ba, "Delete process");
-
-    //---TRK------------------------------------------------------
-    //  Command: 0x80 Acknowledge
-    //    Error: 0x00
-    // [80 24 00]
-
-    foreach (const Breakpoint &bp, m_breakpoints)
-        clearTrkBreakpoint(bp);
-
-    sendTrkMessage(0x02, CB(handleDisconnect));
-    m_startInferiorTriggered = false;
-    //---IDE------------------------------------------------------
-    //  Command: 0x1C Clear Break
-    // [1C 25 00 00 00 0A 78 6A 43 40]
-
-        //---TRK------------------------------------------------------
-        //  Command: 0xA1 Notify Deleted
-        // [A1 09 00 00 00 00 00 00 00 00 07 1F]
-        //---IDE------------------------------------------------------
-        //  Command: 0x80 Acknowledge
-        //    Error: 0x00
-        // [80 09 00]
-
-    //---TRK------------------------------------------------------
-    //  Command: 0x80 Acknowledge
-    //    Error: 0x00
-    // [80 25 00]
-
-    //---IDE------------------------------------------------------
-    //  Command: 0x1C Clear Break
-    // [1C 26 00 00 00 0B 78 6A 43 70]
-    //---TRK------------------------------------------------------
-    //  Command: 0x80 Acknowledge
-    //    Error: 0x00
-    // [80 26 00]
-
-
-    //---IDE------------------------------------------------------
-    //  Command: 0x02 Disconnect
-    // [02 27]
-//    sendTrkMessage(0x02, CB(handleDisconnect));
-    //---TRK------------------------------------------------------
-    //  Command: 0x80 Acknowledge
-    // Error: 0x00
-}
-
-static inline QByteArray memoryRequestTrkMessage(uint addr, uint len, int pid, int tid)
-{
-    QByteArray ba;
-    appendByte(&ba, 0x08); // Options, FIXME: why?
-    appendShort(&ba, len);
-    appendInt(&ba, addr);
-    appendInt(&ba, pid);
-    appendInt(&ba, tid);
-    return ba;
-}
-
-void Adapter::readMemory(uint addr, uint len)
-{
-    Q_ASSERT(len < (2 << 16));
-
-    // We try to get medium-sized chunks of data from the device
-    if (m_verbose > 2)
-        logMessage(QString::fromLatin1("readMemory %1 bytes from 0x%2 blocksize=%3").arg(len).arg(addr, 0, 16).arg(MemoryChunkSize));
-
-    if (m_bufferedMemoryRead) {
-        uint blockaddr = (addr / MemoryChunkSize) * MemoryChunkSize;
-        for (; blockaddr < addr + len; blockaddr += MemoryChunkSize) {
-            if (!m_snapshot.memory.contains(blockaddr)) {
-                if (m_verbose)
-                    logMessage(QString::fromLatin1("Requesting buffered memory %1 bytes from 0x%2").arg(MemoryChunkSize).arg(blockaddr, 0, 16));
-                sendTrkMessage(0x10, CB(handleReadMemoryBuffered),
-                               memoryRequestTrkMessage(blockaddr, MemoryChunkSize, m_session.pid, m_session.tid),
-                               QVariant(blockaddr), true);
-            }
-        }
-        const qulonglong cookie = (qulonglong(addr) << 32) + len;
-        sendTrkMessage(TRK_WRITE_QUEUE_NOOP_CODE, CB(reportReadMemoryBuffered), QByteArray(), cookie);
-    } else {
-        if (m_verbose)
-            logMessage(QString::fromLatin1("Requesting unbuffered memory %1 bytes from 0x%2").arg(len).arg(addr, 0, 16));
-        sendTrkMessage(0x10, CB(handleReadMemoryUnbuffered),
-                       memoryRequestTrkMessage(addr, len, m_session.pid, m_session.tid),
-                       QVariant(addr), true);
-    }
-}
-
-void Adapter::startInferiorIfNeeded()
-{
-    if (m_startInferiorTriggered)
-        return;
-    if (m_session.pid != 0) {
-        logMessage("Process already 'started'");
-        return;
-    }
-    // It's not started yet
-    m_startInferiorTriggered = true;
-    QByteArray ba;
-    appendByte(&ba, 0); // ?
-    appendByte(&ba, 0); // ?
-    appendByte(&ba, 0); // ?
-
-    QByteArray file("C:\\sys\\bin\\filebrowseapp.exe");
-    appendString(&ba, file, TargetByteOrder);
-    sendTrkMessage(0x40, CB(handleCreateProcess), ba); // Create Item
-}
-
-void Adapter::interruptInferior()
-{
-    QByteArray ba;
-    // stop the thread (2) or the process (1) or the whole system (0)
-    appendByte(&ba, 1);
-    appendInt(&ba, m_session.pid);
-    appendInt(&ba, m_session.tid); // threadID: 4 bytes Variable number of bytes.
-    sendTrkMessage(0x1A, Callback(), ba, "Interrupting...");
-}
-
-void Adapter::connectProcess(QProcess *proc)
-{
-    connect(proc, SIGNAL(error(QProcess::ProcessError)),
-        this, SLOT(handleProcError(QProcess::ProcessError)));
-    connect(proc, SIGNAL(finished(int, QProcess::ExitStatus)),
-        this, SLOT(handleProcFinished(int, QProcess::ExitStatus)));
-    connect(proc, SIGNAL(readyReadStandardError()),
-        this, SLOT(handleProcReadyReadStandardError()));
-    connect(proc, SIGNAL(readyReadStandardOutput()),
-        this, SLOT(handleProcReadyReadStandardOutput()));
-    connect(proc, SIGNAL(started()),
-        this, SLOT(handleProcStarted()));
-    connect(proc, SIGNAL(stateChanged(QProcess::ProcessState)),
-        this, SLOT(handleProcStateChanged(QProcess::ProcessState)));
-}
-
-void Adapter::sendOutput(QObject *sender, const QString &data)
-{
-    if (sender)
-        emit output(sender->objectName() + " : ", data);
-    else
-        emit output(QString(), data);
-}
-
-void Adapter::handleProcError(QProcess::ProcessError error)
-{
-    sendOutput(sender(), QString("Process Error %1").arg(error));
-}
-
-void Adapter::handleProcFinished(int exitCode, QProcess::ExitStatus exitStatus)
-{
-    sendOutput(sender(),
-        QString("ProcessFinished %1 %2").arg(exitCode).arg(exitStatus));
-}
-
-void Adapter::handleProcReadyReadStandardError()
-{
-    QByteArray ba = qobject_cast<QProcess *>(sender())->readAllStandardError();
-    sendOutput(sender(), QString("stderr: %1").arg(QString::fromLatin1(ba)));
-}
-
-void Adapter::handleProcReadyReadStandardOutput()
-{
-    QByteArray ba = qobject_cast<QProcess *>(sender())->readAllStandardOutput();
-    sendOutput(sender(), QString("stdout: %1").arg(QString::fromLatin1(ba)));
-}
-
-void Adapter::handleProcStarted()
-{
-    sendOutput(sender(), QString("Process Started"));
-}
-
-void Adapter::handleProcStateChanged(QProcess::ProcessState newState)
-{
-    sendOutput(sender(), QString("Process State %1").arg(newState));
-}
-
-void Adapter::run()
-{
-    startServer();
-    sendOutput("### Starting Adapter");
-
-    m_rfcommProc.start("rfcomm listen /dev/rfcomm0 1");
-
-    uid_t userId = getuid();
-    if (m_trkServerName.isEmpty())
-        m_trkServerName = QString("TRKSERVER-%1").arg(userId);
-}
-
-void Adapter::startGdb()
-{
-    logMessage("STARTING GDB");
-    QStringList gdbArgs;
-    gdbArgs.append("--nx"); // Do not read .gdbinit file
-    gdbArgs.append("-i");
-    gdbArgs.append("mi");
-    m_gdbProc.start(QDir::currentPath() + "/cs-gdb", gdbArgs);
-    m_gdbProc.waitForStarted();
-
-    //writeToGdb("set remote noack-packet on");
-    writeToGdb("set confirm off");
-    writeToGdb("set endian " + m_endianness);
-    //writeToGdb("set debug remote 1");
-    //writeToGdb("target remote " + m_gdbServerName);
-    writeToGdb("target extended-remote " + m_gdbServerName);
-    //writeToGdb("file filebrowseapp.sym");
-//    writeToGdb("add-symbol-file filebrowseapp.sym " + m_baseAddress);
-//    writeToGdb("symbol-file filebrowseapp.sym");
-//    writeToGdb("print E32Main");
-//    writeToGdb("break E32Main");
-    //writeToGdb("continue");
-    //writeToGdb("info files");
-    //writeToGdb("file filebrowseapp.sym -readnow");
-}
-
-void Adapter::writeToGdb(const QString &msg)
-{
-    logMessage("<- GDB: " + msg);
-    m_gdbProc.write(msg.toLatin1() + "\n");
-}
+};
 
 ///////////////////////////////////////////////////////////////////////
 //
@@ -1611,55 +165,65 @@ void Adapter::writeToGdb(const QString &msg)
 //
 ///////////////////////////////////////////////////////////////////////
 
-class RunnerGui : public QTextEdit
+using namespace Debugger::Internal;
+
+class RunnerGui : public QMainWindow
 {
     Q_OBJECT
 
 public:
-    RunnerGui(Adapter *adapter);
-    void keyPressEvent(QKeyEvent *ev);
+    RunnerGui(SymbianAdapter *adapter);
 
 private slots:
-    void handleOutput(const QString &senderName, const QString &data);
+    void executeStepICommand() { executeCommand("-exec-step-instruction"); }
+    void executeStepCommand() { executeCommand("-exec-step"); }
+    void executeNextICommand() { executeCommand("-exec-next-instruction"); }
+    void executeNextCommand() { executeCommand("-exec-next"); }
+    void executeContinueCommand() { executeCommand("-exec-continue"); }
+    void executeDisassICommand() { executeCommand("disass $pc $pc+4"); }
 
 private:
-    Adapter *m_adapter;
+    void executeCommand(const QString &cmd) { m_adapter->executeCommand(cmd); }
+    void connectAction(QAction *&, QString name, const char *slot);
+
+    SymbianAdapter *m_adapter;
+    TextEdit m_textEdit;
+    QToolBar m_toolBar;
+    QAction *m_stepIAction;
+    QAction *m_stepAction;
+    QAction *m_nextIAction;
+    QAction *m_nextAction;
+    QAction *m_disassIAction;
+    QAction *m_continueAction;
 };
 
-RunnerGui::RunnerGui(Adapter *adapter)
-    : m_adapter(adapter) 
+RunnerGui::RunnerGui(SymbianAdapter *adapter)
+    : m_adapter(adapter)
 {
     resize(1200, 1000);
-    connect(adapter, SIGNAL(output(QString,QString)),
-        this, SLOT(handleOutput(QString,QString)));
-}
+    setCentralWidget(&m_textEdit);
 
-void RunnerGui::handleOutput(const QString &senderName, const QString &data)
-{
-    append(senderName + data);
-    QTextCursor tc = textCursor();
-    tc.movePosition(QTextCursor::End);
-    setTextCursor(tc);
-    if (senderName.startsWith("GDB PROCESS")) {
-        QString str = data;
-        int pos = str.indexOf("~\"");
-        if (pos != -1)
-            str = str.mid(pos + 2);
-        str.replace("\\t", QString(QChar(0x09)));
-        str.replace("\\n", QString("\n"));
-        insertHtml("<b>" + str + "</b>");
-        setCurrentCharFormat(QTextCharFormat());
-    }
-    ensureCursorVisible();
+    addToolBar(&m_toolBar);
 
+    connectAction(m_stepIAction, "Step Inst", SLOT(executeStepICommand()));
+    connectAction(m_stepAction, "Step", SLOT(executeStepCommand()));
+    connectAction(m_nextIAction, "Next Inst", SLOT(executeNextICommand()));
+    connectAction(m_nextAction, "Next", SLOT(executeNextCommand()));
+    connectAction(m_disassIAction, "Disass Inst", SLOT(executeDisassICommand()));
+    connectAction(m_continueAction, "Continue", SLOT(executeContinueCommand()));
+
+    connect(adapter, SIGNAL(output(QString,QString)),
+        &m_textEdit, SLOT(handleOutput(QString,QString)));
+    connect(&m_textEdit, SIGNAL(executeCommand(QString)),
+        m_adapter, SLOT(executeCommand(QString)));
 }
 
-void RunnerGui::keyPressEvent(QKeyEvent *ev)
+void RunnerGui::connectAction(QAction *&action, QString name, const char *slot)
 {
-    if (ev->modifiers() == Qt::ControlModifier && ev->key() == Qt::Key_Return)
-        m_adapter->executeGdbCommand(textCursor().block().text());
-    else
-        QTextEdit::keyPressEvent(ev);
+    action = new QAction(this);
+    action->setText(name);
+    m_toolBar.addAction(action);
+    connect(action, SIGNAL(triggered()), this, slot);
 }
 
 ///////////////////////////////////////////////////////////////////////
@@ -1671,7 +235,7 @@ void RunnerGui::keyPressEvent(QKeyEvent *ev)
 int main(int argc, char *argv[])
 {
     QApplication app(argc, argv);
-    Adapter adapter;
+    SymbianAdapter adapter;
     RunnerGui gui(&adapter);
     gui.show();
     QTimer::singleShot(0, &adapter, SLOT(run()));
diff --git a/tests/manual/trk/runner.pro b/tests/manual/trk/runner.pro
index 4ced7ccd71abbd0302dc062e6acca3867e284054..21461da2d94b33ce1a3df8759d3894afa3fa154d 100644
--- a/tests/manual/trk/runner.pro
+++ b/tests/manual/trk/runner.pro
@@ -1,15 +1,21 @@
 
 TEMPLATE = app
 
+DEBUGGERHOME = ../../../src/plugins/debugger/symbian
+INCLUDEPATH *= $$DEBUGGERHOME
+
 QT += network
 
 win32:CONFIG+=console
 
 HEADERS += \
-    trkutils.h \
-    trkdevicex.h \
+    $$DEBUGGERHOME/../gdb/gdbprocessbase.h \
+    $$DEBUGGERHOME/trkutils.h \
+    $$DEBUGGERHOME/trkclient.h \
+    $$DEBUGGERHOME/symbianadapter.h \
 
 SOURCES += \
-    runner.cpp \
-    trkutils.cpp \
-    trkdevicex.cpp \
+    $$DEBUGGERHOME/trkutils.cpp \
+    $$DEBUGGERHOME/trkclient.cpp \
+    $$DEBUGGERHOME/symbianadapter.cpp \
+    $$PWD/runner.cpp \
diff --git a/tests/manual/trk/trkdevice.h b/tests/manual/trk/trkdevice.h
index 7b2a5dbcd38fd2b1286353d5db6ba94126fc4300..7bfdff7411b269816d142972d97fba4d8c441426 100644
--- a/tests/manual/trk/trkdevice.h
+++ b/tests/manual/trk/trkdevice.h
@@ -111,7 +111,7 @@ public:
     explicit TrkWriteQueueDevice(QObject *parent = 0);
     virtual ~TrkWriteQueueDevice();
 
-    // Construct as 'TrkWriteQueueDevice::Callback(instance, &Klass::method);'
+    // Construct as 'TrkWriteQueueDevice::Callback(instance, &Class::method);'
     typedef TrkFunctor1<const TrkResult &> Callback;
 
     // Enqueue a message with a notification callback.
diff --git a/tests/manual/trk/trklauncher.pri b/tests/manual/trk/trklauncher.pri
index 3593888b86116b84473a35bf89a1ca0c9466fcce..74b37e42e3cb5179d6b2b90fe7d6f6f8cb092b56 100644
--- a/tests/manual/trk/trklauncher.pri
+++ b/tests/manual/trk/trklauncher.pri
@@ -1,9 +1,15 @@
 DEFINES += DEBUG_TRK=0
-INCLUDEPATH *= $$PWD
-SOURCES += $$PWD/launcher.cpp \
-    $$PWD/trkutils.cpp \
-    $$PWD/trkdevice.cpp
-HEADERS += $$PWD/trkutils.h \
-    $$PWD/trkfunctor.h \
+DEBUGGERHOME = ../../../src/plugins/debugger/symbian
+
+INCLUDEPATH *= $$DEBUGGERHOME
+
+SOURCES += \
+    $$DEBUGGERHOME/trkutils.cpp \
+    $$PWD/trkdevice.cpp \
+    $$PWD/launcher.cpp \
+
+HEADERS += \
+    $$DEBUGGERHOME/trkutils.h \
+    $$DEBUGGERHOME/trkfunctor.h \
     $$PWD/trkdevice.h \
     $$PWD/launcher.h
diff --git a/tests/manual/trk/trkserver.pro b/tests/manual/trk/trkserver.pro
index a333dc2c363c49624bd2fc934c56edba0aec518a..6fbbc85c06cddef88064d35dc19b08f98e6e3626 100644
--- a/tests/manual/trk/trkserver.pro
+++ b/tests/manual/trk/trkserver.pro
@@ -1,12 +1,17 @@
 
 TEMPLATE = app
 
+DEBUGGERHOME = ../../../src/plugins/debugger/symbian
+
 QT = core network
 win32:CONFIG+=console
 
+INCLUDEPATH *= $$DEBUGGERHOME
+
+
 HEADERS += \
-    trkutils.h
+    $$DEBUGGERHOME/trkutils.h
 
 SOURCES += \
-    trkutils.cpp \
-    trkserver.cpp
+    $$DEBUGGERHOME/trkutils.cpp \
+    $$PWD/trkserver.cpp