OSDN Git Service

Experimental lldb engine host
authorArvid Ephraim Picciani <arvid.picciani@nokia.com>
Fri, 8 Oct 2010 10:14:51 +0000 (12:14 +0200)
committerArvid Ephraim Picciani <arvid.picciani@nokia.com>
Tue, 9 Nov 2010 13:01:27 +0000 (14:01 +0100)
src/plugins/debugger/debugger.pro
src/plugins/debugger/debuggerconstants.h
src/plugins/debugger/debuggerrunner.cpp
src/plugins/debugger/lldb/ipcengineguest.cpp [new file with mode: 0644]
src/plugins/debugger/lldb/ipcengineguest.h [new file with mode: 0644]
src/plugins/debugger/lldb/ipcenginehost.cpp [new file with mode: 0644]
src/plugins/debugger/lldb/ipcenginehost.h [new file with mode: 0644]
src/plugins/debugger/lldb/lldbenginehost.cpp [new file with mode: 0644]
src/plugins/debugger/lldb/lldbenginehost.h [new file with mode: 0644]
src/plugins/debugger/lldb/lldbhost.pri [new file with mode: 0644]

index 1b066a8..3ab4320 100644 (file)
@@ -123,6 +123,7 @@ include(cdb/cdb.pri)
 include(gdb/gdb.pri)
 include(script/script.pri)
 include(pdb/pdb.pri)
+include(lldb/lldbhost.pri)
 
 contains(QT_CONFIG, declarative) {
     QT += declarative
index c9e419f..30688ba 100644 (file)
@@ -208,7 +208,8 @@ enum DebuggerEngineType
     PdbEngineType     = 0x08,
     TcfEngineType     = 0x10,
     QmlEngineType     = 0x20,
-    QmlCppEngineType     = 0x40,
+    QmlCppEngineType  = 0x40,
+    LLDBEngineType  = 0x80,
     AllEngineTypes = GdbEngineType
         | ScriptEngineType
         | CdbEngineType
@@ -216,6 +217,7 @@ enum DebuggerEngineType
         | TcfEngineType
         | QmlEngineType
         | QmlCppEngineType
+        | LLDBEngineType
 };
 
 enum DebuggerLanguage
index 949e7ea..aa09519 100644 (file)
@@ -39,6 +39,7 @@
 #include "gdb/remoteplaingdbadapter.h"
 #include "qml/qmlengine.h"
 #include "qml/qmlcppengine.h"
+#include "lldb/lldbenginehost.h"
 
 #ifdef Q_OS_WIN
 #  include "peutils.h"
@@ -72,6 +73,7 @@ DebuggerEngine *createPdbEngine(const DebuggerStartParameters &);
 DebuggerEngine *createTcfEngine(const DebuggerStartParameters &);
 DebuggerEngine *createQmlEngine(const DebuggerStartParameters &);
 DebuggerEngine *createQmlCppEngine(const DebuggerStartParameters &);
+DebuggerEngine *createLLDBEngine(const DebuggerStartParameters &);
 
 bool checkGdbConfiguration(int toolChain, QString *errorMsg, QString *settingsPage);
 
@@ -429,6 +431,9 @@ void DebuggerRunControl::createEngine(const DebuggerStartParameters &startParams
     if (sp.processArgs.size() >= 5 && sp.processArgs.at(0) == _("@tcf@"))
         engineType = GdbEngineType;
 
+    if (sp.processArgs.contains( _("@lldb@")))
+        engineType = LLDBEngineType;
+
     if (engineType == NoEngineType
             && sp.startMode != AttachToRemote
             && !sp.executable.isEmpty())
@@ -477,6 +482,8 @@ void DebuggerRunControl::createEngine(const DebuggerStartParameters &startParams
             if (Internal::GdbEngine *embeddedGdbEngine = gdbEngine())
                 initGdbEngine(embeddedGdbEngine);
             break;
+        case LLDBEngineType:
+            d->m_engine = Internal::createLLDBEngine(sp);
        case NoEngineType:
        case AllEngineTypes:
             break;
diff --git a/src/plugins/debugger/lldb/ipcengineguest.cpp b/src/plugins/debugger/lldb/ipcengineguest.cpp
new file mode 100644 (file)
index 0000000..0a21927
--- /dev/null
@@ -0,0 +1,608 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2010 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 "ipcengineguest.h"
+#include "ipcenginehost.h"
+#include "breakpoint.h"
+#include "stackframe.h"
+#include "threaddata.h"
+#include "debuggerstreamops.h"
+
+#include <QSysInfo>
+#include <QDebug>
+#include <QFileInfo>
+#include <QTimer>
+#include <utils/qtcassert.h>
+
+#if Q_BYTE_ORDER == Q_LITTLE_ENDIAN
+#define SET_NATIVE_BYTE_ORDER(x) x.setByteOrder(QDataStream::LittleEndian)
+#else
+#define SET_NATIVE_BYTE_ORDER(x) x.setByteOrder(QDataStream::BigEndian)
+#endif
+
+namespace Debugger {
+namespace Internal {
+
+IPCEngineGuest::IPCEngineGuest()
+    : QObject()
+    , m_local_host(0)
+    , m_nextMessagePayloadSize(0)
+    , m_cookie(1)
+    , m_device(0)
+{
+}
+
+IPCEngineGuest::~IPCEngineGuest()
+{
+}
+
+void IPCEngineGuest::setLocalHost(IPCEngineHost * h)
+{
+    m_local_host = h;
+}
+
+void IPCEngineGuest::setHostDevice(QIODevice * d)
+{
+    if (m_device) {
+        disconnect(m_device, SIGNAL(readyRead()), this, SLOT(readyRead()));
+        delete m_device;
+    }
+    m_device = d;
+    if (m_device)
+        connect(m_device, SIGNAL(readyRead()), this, SLOT(readyRead()));
+}
+
+void IPCEngineGuest::rpcCall(IPCEngineGuest::Function f, QByteArray payload )
+{
+#if 0
+    if (m_local_host) {
+        QMetaObject::invokeMethod(m_local_host,
+                "rpcCallback",
+                Qt::QueuedConnection,
+                Q_ARG(quint64, f),
+                Q_ARG(QByteArray, payload));
+    } else
+#endif
+    if (m_device) {
+        {
+            QDataStream s(m_device);
+            SET_NATIVE_BYTE_ORDER(s);
+            s << m_cookie++;
+            s << (quint64) f;
+            s << (quint64) payload.size();
+        }
+        m_device->write(payload);
+        m_device->putChar('T');
+    }
+}
+
+void IPCEngineGuest::readyRead()
+{
+    if (!m_nextMessagePayloadSize) {
+        if (quint64(m_device->bytesAvailable()) < (sizeof(quint64) * 3))
+            return;
+        QDataStream s(m_device);
+        SET_NATIVE_BYTE_ORDER(s);
+        s >> m_nextMessageCookie;
+        s >> m_nextMessageFunction;
+        s >> m_nextMessagePayloadSize;
+        m_nextMessagePayloadSize += 1; // terminator and "got header" marker
+    }
+
+    quint64 ba = m_device->bytesAvailable();
+    if (ba < m_nextMessagePayloadSize)
+        return;
+
+    qint64 rrr = (m_nextMessagePayloadSize);
+    QByteArray payload = m_device->read(rrr);
+    if (quint64(payload.size()) != m_nextMessagePayloadSize || !payload.endsWith('T')) {
+        showMessage(QLatin1String("IPC Error: corrupted frame"));
+        showMessage(tr("Fatal engine shutdown. Incompatible binary or ipc error."), LogError);
+        showStatusMessage(tr("Fatal engine shutdown. Incompatible binary or ipc error."));
+        notifyEngineIll();
+        return;
+    }
+    payload.chop(1);
+    rpcCallback(m_nextMessageFunction, payload);
+    m_nextMessagePayloadSize = 0;
+
+    if (quint64(m_device->bytesAvailable ()) >= (sizeof(quint64) * 3))
+        QTimer::singleShot(0, this, SLOT(readyRead()));
+}
+
+void IPCEngineGuest::rpcCallback(quint64 f, QByteArray payload )
+{
+    switch (f) {
+        default:
+            showMessage(QLatin1String("IPC Error: unhandled id in host to guest call"));
+            showMessage(tr("Fatal engine shutdown. Incompatible binary or ipc error."), LogError);
+            showStatusMessage(tr("Fatal engine shutdown. Incompatible binary or ipc error."));
+            notifyEngineIll();
+            break;
+        case IPCEngineHost::SetupIPC:
+            {
+                QDataStream s(payload);
+                SET_NATIVE_BYTE_ORDER(s);
+                int version;
+                s >> version;
+                Q_ASSERT(version == 1);
+            }
+            break;
+        case IPCEngineHost::StateChanged:
+            {
+                QDataStream s(payload);
+                SET_NATIVE_BYTE_ORDER(s);
+                quint64 st;
+                s >> st;
+                m_state = (DebuggerState)st;
+            }
+            break;
+        case IPCEngineHost::SetupEngine:
+            setupEngine();
+            break;
+        case IPCEngineHost::SetupInferior:
+            {
+                QDataStream s(payload);
+                SET_NATIVE_BYTE_ORDER(s);
+                QString executable;
+                QStringList arguments;
+                QStringList environment;
+                s >> executable;
+                s >> arguments;
+                s >> environment;
+                setupInferior(executable, arguments, environment);
+            }
+            break;
+        case IPCEngineHost::RunEngine:
+            runEngine();
+            break;
+        case IPCEngineHost::ShutdownInferior:
+            shutdownInferior();
+            break;
+        case IPCEngineHost::ShutdownEngine:
+            shutdownEngine();
+            break;
+        case IPCEngineHost::DetachDebugger:
+            detachDebugger();
+            break;
+        case IPCEngineHost::ExecuteStep:
+            executeStep();
+            break;
+        case IPCEngineHost::ExecuteStepOut:
+            executeStepOut();
+            break;
+        case IPCEngineHost::ExecuteNext:
+            executeNext();
+            break;
+        case IPCEngineHost::ExecuteStepI:
+            executeStepI();
+            break;
+        case IPCEngineHost::ExecuteNextI:
+            executeNextI();
+            break;
+        case IPCEngineHost::ContinueInferior:
+            continueInferior();
+            break;
+        case IPCEngineHost::InterruptInferior:
+            interruptInferior();
+            break;
+        case IPCEngineHost::ExecuteRunToLine:
+            {
+                QDataStream s(payload);
+                SET_NATIVE_BYTE_ORDER(s);
+                QString fileName;
+                quint64 lineNumber;
+                s >> fileName;
+                s >> lineNumber;
+                executeRunToLine(fileName, lineNumber);
+            }
+            break;
+        case IPCEngineHost::ExecuteRunToFunction:
+            {
+                QDataStream s(payload);
+                SET_NATIVE_BYTE_ORDER(s);
+                QString functionName;
+                s >> functionName;
+                executeRunToFunction(functionName);
+            }
+            break;
+        case IPCEngineHost::ExecuteJumpToLine:
+            {
+                QDataStream s(payload);
+                SET_NATIVE_BYTE_ORDER(s);
+                QString fileName;
+                quint64 lineNumber;
+                s >> fileName;
+                s >> lineNumber;
+                executeJumpToLine(fileName, lineNumber);
+            }
+            break;
+        case IPCEngineHost::ActivateFrame:
+            {
+                QDataStream s(payload);
+                SET_NATIVE_BYTE_ORDER(s);
+                quint64 id;
+                s >> id;
+                activateFrame(id);
+            }
+            break;
+        case IPCEngineHost::SelectThread:
+            {
+                QDataStream s(payload);
+                SET_NATIVE_BYTE_ORDER(s);
+                quint64 id;
+                s >> id;
+                selectThread(id);
+            }
+            break;
+        case IPCEngineHost::Disassemble:
+            {
+                QDataStream s(payload);
+                SET_NATIVE_BYTE_ORDER(s);
+                quint64 pc;
+                s >> pc;
+                disassemble(pc);
+            }
+            break;
+        case IPCEngineHost::AddBreakpoint:
+            {
+                QDataStream s(payload);
+                SET_NATIVE_BYTE_ORDER(s);
+                BreakpointData d;
+                s >> d;
+                addBreakpoint(d);
+            }
+            break;
+        case IPCEngineHost::RemoveBreakpoint:
+            {
+                QDataStream s(payload);
+                SET_NATIVE_BYTE_ORDER(s);
+                quint64 token;
+                s >> token;
+                removeBreakpoint(token);
+            }
+            break;
+        case IPCEngineHost::ChangeBreakpoint:
+            {
+                QDataStream s(payload);
+                SET_NATIVE_BYTE_ORDER(s);
+                BreakpointData d;
+                s >> d;
+                changeBreakpoint(d);
+            }
+            break;
+        case IPCEngineHost::RequestUpdateWatchData:
+            {
+                QDataStream s(payload);
+                SET_NATIVE_BYTE_ORDER(s);
+                WatchData data;
+                s >> data;
+                requestUpdateWatchData(data);
+            }
+            break;
+    };
+}
+
+DebuggerState IPCEngineGuest::state() const
+{
+    return m_state;
+}
+
+void IPCEngineGuest::notifyEngineSetupOk()
+{
+    rpcCall(NotifyEngineSetupOk);
+}
+
+void IPCEngineGuest::notifyEngineSetupFailed()
+{
+    rpcCall(NotifyEngineSetupFailed);
+}
+
+void IPCEngineGuest::notifyEngineRunFailed()
+{
+    rpcCall(NotifyEngineRunFailed);
+}
+
+void IPCEngineGuest::notifyInferiorSetupOk()
+{
+    rpcCall(NotifyInferiorSetupOk);
+}
+
+void IPCEngineGuest::notifyInferiorSetupFailed()
+{
+    rpcCall(NotifyInferiorSetupFailed);
+}
+
+void IPCEngineGuest::notifyEngineRunAndInferiorRunOk()
+{
+    rpcCall(NotifyEngineRunAndInferiorRunOk);
+}
+
+void IPCEngineGuest::notifyEngineRunAndInferiorStopOk()
+{
+    rpcCall(NotifyEngineRunAndInferiorStopOk);
+}
+
+void IPCEngineGuest::notifyInferiorRunRequested()
+{
+    rpcCall(NotifyInferiorRunRequested);
+}
+
+void IPCEngineGuest::notifyInferiorRunOk()
+{
+    rpcCall(NotifyInferiorRunOk);
+}
+
+void IPCEngineGuest::notifyInferiorRunFailed()
+{
+    rpcCall(NotifyInferiorRunFailed);
+}
+
+void IPCEngineGuest::notifyInferiorStopOk()
+{
+    rpcCall(NotifyInferiorStopOk);
+}
+
+void IPCEngineGuest::notifyInferiorSpontaneousStop()
+{
+    rpcCall(NotifyInferiorSpontaneousStop);
+}
+
+void IPCEngineGuest::notifyInferiorStopFailed()
+{
+    rpcCall(NotifyInferiorStopFailed);
+}
+
+void IPCEngineGuest::notifyInferiorExited()
+{
+    rpcCall(NotifyInferiorExited);
+}
+
+void IPCEngineGuest::notifyInferiorShutdownOk()
+{
+    rpcCall(NotifyInferiorShutdownOk);
+}
+
+void IPCEngineGuest::notifyInferiorShutdownFailed()
+{
+    rpcCall(NotifyInferiorShutdownFailed);
+}
+
+void IPCEngineGuest::notifyEngineSpontaneousShutdown()
+{
+    rpcCall(NotifyEngineSpontaneousShutdown);
+}
+
+void IPCEngineGuest::notifyEngineShutdownOk()
+{
+    rpcCall(NotifyEngineShutdownOk);
+}
+
+void IPCEngineGuest::notifyEngineShutdownFailed()
+{
+    rpcCall(NotifyEngineShutdownFailed);
+}
+
+void IPCEngineGuest::notifyInferiorIll()
+{
+    rpcCall(NotifyInferiorIll);
+}
+
+void IPCEngineGuest::notifyEngineIll()
+{
+    rpcCall(NotifyEngineIll);
+}
+
+void IPCEngineGuest::notifyInferiorPid(qint64 pid)
+{
+    QByteArray p;
+    {
+        QDataStream s(&p, QIODevice::WriteOnly);
+        SET_NATIVE_BYTE_ORDER(s);
+        s << pid;
+    }
+    rpcCall(NotifyInferiorPid, p);
+}
+
+void IPCEngineGuest::showStatusMessage(const QString &msg, quint64 timeout)
+{
+    QByteArray p;
+    {
+        QDataStream s(&p, QIODevice::WriteOnly);
+        SET_NATIVE_BYTE_ORDER(s);
+        s << msg;
+        s << (qint64)timeout;
+    }
+    rpcCall(ShowStatusMessage, p);
+}
+
+void IPCEngineGuest::showMessage(const QString &msg, quint16 channel, quint64 timeout)
+{
+    QByteArray p;
+    {
+        QDataStream s(&p, QIODevice::WriteOnly);
+        SET_NATIVE_BYTE_ORDER(s);
+        s << msg;
+        s << (qint64)channel;
+        s << (qint64)timeout;
+    }
+    rpcCall(ShowMessage, p);
+}
+
+void IPCEngineGuest::currentFrameChanged(qint64 osid)
+{
+    QByteArray p;
+    {
+        QDataStream s(&p, QIODevice::WriteOnly);
+        SET_NATIVE_BYTE_ORDER(s);
+        s << osid;
+    }
+    rpcCall(CurrentFrameChanged, p);
+}
+
+void IPCEngineGuest::currentThreadChanged(qint64 osid)
+{
+    QByteArray p;
+    {
+        QDataStream s(&p, QIODevice::WriteOnly);
+        SET_NATIVE_BYTE_ORDER(s);
+        s << osid;
+    }
+    rpcCall(CurrentThreadChanged, p);
+}
+
+void IPCEngineGuest::listFrames(const StackFrames &frames)
+{
+    QByteArray p;
+    {
+        QDataStream s(&p, QIODevice::WriteOnly);
+        SET_NATIVE_BYTE_ORDER(s);
+        s << frames;
+    }
+    rpcCall(ListFrames, p);
+}
+
+void IPCEngineGuest::listThreads(const Threads &threads)
+{
+    QByteArray p;
+    {
+        QDataStream s(&p, QIODevice::WriteOnly);
+        SET_NATIVE_BYTE_ORDER(s);
+        s << threads;
+    }
+    rpcCall(ListThreads, p);
+}
+
+void IPCEngineGuest::disassembled(quint64 pc, const QString &da)
+{
+    QByteArray p;
+    {
+        QDataStream s(&p, QIODevice::WriteOnly);
+        SET_NATIVE_BYTE_ORDER(s);
+        s << pc;
+        s << da;
+    }
+    rpcCall(Disassembled, p);
+}
+
+void IPCEngineGuest::notifyAddBreakpointOk(quint64 id)
+{
+    QByteArray p;
+    {
+        QDataStream s(&p, QIODevice::WriteOnly);
+        SET_NATIVE_BYTE_ORDER(s);
+        s << id;
+    }
+    rpcCall(NotifyAddBreakpointOk, p);
+}
+
+void IPCEngineGuest::notifyAddBreakpointFailed(quint64 id)
+{
+    QByteArray p;
+    {
+        QDataStream s(&p, QIODevice::WriteOnly);
+        SET_NATIVE_BYTE_ORDER(s);
+        s << id;
+    }
+    rpcCall(NotifyAddBreakpointFailed, p);
+}
+
+void IPCEngineGuest::notifyRemoveBreakpointOk(quint64 id)
+{
+    QByteArray p;
+    {
+        QDataStream s(&p, QIODevice::WriteOnly);
+        SET_NATIVE_BYTE_ORDER(s);
+        s << id;
+    }
+    rpcCall(NotifyRemoveBreakpointOk, p);
+}
+
+void IPCEngineGuest::notifyRemoveBreakpointFailed(quint64 id)
+{
+    QByteArray p;
+    {
+        QDataStream s(&p, QIODevice::WriteOnly);
+        SET_NATIVE_BYTE_ORDER(s);
+        s << id;
+    }
+    rpcCall(NotifyRemoveBreakpointFailed, p);
+}
+
+void IPCEngineGuest::notifyChangeBreakpointOk(quint64 id)
+{
+    QByteArray p;
+    {
+        QDataStream s(&p, QIODevice::WriteOnly);
+        SET_NATIVE_BYTE_ORDER(s);
+        s << id;
+    }
+    rpcCall(NotifyChangeBreakpointOk, p);
+}
+
+void IPCEngineGuest::notifyChangeBreakpointFailed(quint64 id)
+{
+    QByteArray p;
+    {
+        QDataStream s(&p, QIODevice::WriteOnly);
+        SET_NATIVE_BYTE_ORDER(s);
+        s << id;
+    }
+    rpcCall(NotifyChangeBreakpointFailed, p);
+}
+
+void IPCEngineGuest::notifyBreakpointAdjusted(const Internal::BreakpointData &bp)
+{
+    QByteArray p;
+    {
+        QDataStream s(&p, QIODevice::WriteOnly);
+        SET_NATIVE_BYTE_ORDER(s);
+        s << bp;
+    }
+    rpcCall(NotifyBreakpointAdjusted, p);
+}
+
+void IPCEngineGuest::updateWatchData(bool fullCycle, const QList<Internal::WatchData> &wd)
+{
+    QByteArray p;
+    {
+        QDataStream s(&p, QIODevice::WriteOnly);
+        SET_NATIVE_BYTE_ORDER(s);
+        s << fullCycle;
+        s << quint64(wd.count());
+        for (int i = 0; i < wd.count(); i++)
+            s << wd.at(i);
+    }
+    rpcCall(UpdateWatchData, p);
+}
+
+} // namespace Internal
+} // namespace Debugger
+
+
diff --git a/src/plugins/debugger/lldb/ipcengineguest.h b/src/plugins/debugger/lldb/ipcengineguest.h
new file mode 100644 (file)
index 0000000..e532382
--- /dev/null
@@ -0,0 +1,185 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2010 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_IPCENGINE_H
+#define DEBUGGER_IPCENGINE_H
+
+#include "debuggerengine.h"
+#include "threadshandler.h"
+#include "stackhandler.h"
+#include "breakhandler.h"
+
+#include <QtCore/QQueue>
+#include <QtCore/QVariant>
+#include <QtCore/QThread>
+
+namespace Debugger {
+namespace Internal {
+
+class IPCEngineHost;
+class IPCEngineGuest : public QObject
+{
+    Q_OBJECT
+
+public:
+    IPCEngineGuest();
+    virtual ~IPCEngineGuest();
+
+    void setLocalHost(IPCEngineHost *);
+    void setHostDevice(QIODevice *);
+
+    virtual void setupEngine() = 0;
+    virtual void setupInferior(const QString &executeable,
+            const QStringList &arguments, const QStringList &environment) = 0;
+    virtual void runEngine() = 0;
+    virtual void shutdownInferior() = 0;
+    virtual void shutdownEngine() = 0;
+    virtual void detachDebugger() = 0;
+    virtual void executeStep() = 0;
+    virtual void executeStepOut() = 0;
+    virtual void executeNext() = 0;
+    virtual void executeStepI() = 0;
+    virtual void executeNextI() = 0;
+    virtual void continueInferior() = 0;
+    virtual void interruptInferior() = 0;
+    virtual void executeRunToLine(const QString &fileName, int lineNumber) = 0;
+    virtual void executeRunToFunction(const QString &functionName) = 0;
+    virtual void executeJumpToLine(const QString &fileName, int lineNumber) = 0;
+    virtual void activateFrame(qint64 token) = 0;
+    virtual void selectThread(qint64 token) = 0;
+    virtual void disassemble(quint64 pc) = 0;
+    virtual void addBreakpoint(const Internal::BreakpointData &bp) = 0;
+    virtual void removeBreakpoint(quint64 id) = 0;
+    virtual void changeBreakpoint(const Internal::BreakpointData &bp) = 0;
+    virtual void requestUpdateWatchData(const Internal::WatchData &data,
+            const Internal::WatchUpdateFlags & flags = Internal::WatchUpdateFlags()) = 0;
+
+    enum Function
+    {
+        NotifyEngineSetupOk              = 1,
+        NotifyEngineSetupFailed          = 2,
+        NotifyEngineRunFailed            = 3,
+        NotifyInferiorSetupOk            = 4,
+        NotifyInferiorSetupFailed        = 5,
+        NotifyEngineRunAndInferiorRunOk  = 6,
+        NotifyEngineRunAndInferiorStopOk = 7,
+        NotifyInferiorRunRequested       = 8,
+        NotifyInferiorRunOk              = 9,
+        NotifyInferiorRunFailed          = 10,
+        NotifyInferiorStopOk             = 11,
+        NotifyInferiorSpontaneousStop    = 12,
+        NotifyInferiorStopFailed         = 13,
+        NotifyInferiorExited             = 14,
+        NotifyInferiorShutdownOk         = 15,
+        NotifyInferiorShutdownFailed     = 16,
+        NotifyEngineSpontaneousShutdown  = 17,
+        NotifyEngineShutdownOk           = 18,
+        NotifyEngineShutdownFailed       = 19,
+        NotifyInferiorIll                = 20,
+        NotifyEngineIll                  = 21,
+        NotifyInferiorPid                = 22,
+        ShowStatusMessage                = 23,
+        ShowMessage                      = 24,
+        CurrentFrameChanged              = 25,
+        CurrentThreadChanged             = 26,
+        ListFrames                       = 27,
+        ListThreads                      = 28,
+        Disassembled                     = 29,
+        NotifyAddBreakpointOk            = 30,
+        NotifyAddBreakpointFailed        = 31,
+        NotifyRemoveBreakpointOk         = 32,
+        NotifyRemoveBreakpointFailed     = 33,
+        NotifyChangeBreakpointOk         = 34,
+        NotifyChangeBreakpointFailed     = 35,
+        NotifyBreakpointAdjusted         = 36,
+        UpdateWatchData                  = 47
+    };
+    Q_ENUMS(Function);
+
+    DebuggerState state() const;
+    void notifyEngineSetupOk();
+    void notifyEngineSetupFailed();
+    void notifyEngineRunFailed();
+    void notifyInferiorSetupOk();
+    void notifyInferiorSetupFailed();
+    void notifyEngineRunAndInferiorRunOk();
+    void notifyEngineRunAndInferiorStopOk();
+    void notifyInferiorRunRequested();
+    void notifyInferiorRunOk();
+    void notifyInferiorRunFailed();
+    void notifyInferiorStopOk();
+    void notifyInferiorSpontaneousStop();
+    void notifyInferiorStopFailed();
+    void notifyInferiorExited();
+    void notifyInferiorShutdownOk();
+    void notifyInferiorShutdownFailed();
+    void notifyEngineSpontaneousShutdown();
+    void notifyEngineShutdownOk();
+    void notifyEngineShutdownFailed();
+    void notifyInferiorIll();
+    void notifyEngineIll();
+    void notifyInferiorPid(qint64 pid);
+    void showMessage(const QString &msg, quint16 channel = LogDebug, quint64 timeout = -1);
+    void showStatusMessage(const QString &msg, quint64 timeout = -1);
+
+    void currentFrameChanged(qint64 token);
+    void currentThreadChanged(qint64 token);
+    void listFrames(const StackFrames &);
+    void listThreads(const Threads &);
+    void disassembled(quint64 pc, const QString &da);
+
+    void notifyAddBreakpointOk(quint64 id);
+    void notifyAddBreakpointFailed(quint64 id);
+    void notifyRemoveBreakpointOk(quint64 id);
+    void notifyRemoveBreakpointFailed(quint64 id);
+    void notifyChangeBreakpointOk(quint64 id);
+    void notifyChangeBreakpointFailed(quint64 id);
+    void notifyBreakpointAdjusted(const  Internal::BreakpointData &bp);
+
+    void updateWatchData(bool fullCycle, const QList<Internal::WatchData> &);
+
+    void rpcCall(Function f, QByteArray payload = QByteArray());
+public slots:
+    void rpcCallback(quint64 f, QByteArray payload = QByteArray());
+private slots:
+    void readyRead();
+private:
+    IPCEngineHost *m_local_host;
+    quint64 m_nextMessageCookie;
+    quint64 m_nextMessageFunction;
+    quint64 m_nextMessagePayloadSize;
+    quint64 m_cookie;
+    QIODevice *m_device;
+    DebuggerState m_state;
+};
+
+} // namespace Internal
+} // namespace Debugger
+
+#endif // DEBUGGER_LLDBENGINE_H
diff --git a/src/plugins/debugger/lldb/ipcenginehost.cpp b/src/plugins/debugger/lldb/ipcenginehost.cpp
new file mode 100644 (file)
index 0000000..277fd26
--- /dev/null
@@ -0,0 +1,603 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2010 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 "ipcenginehost.h"
+#include "ipcengineguest.h"
+#include "breakhandler.h"
+#include "breakpoint.h"
+#include "moduleshandler.h"
+#include "registerhandler.h"
+#include "stackhandler.h"
+#include "watchhandler.h"
+#include "watchutils.h"
+#include "threadshandler.h"
+#include "debuggeragents.h"
+#include "debuggerstreamops.h"
+
+#include <QSysInfo>
+#include <QDebug>
+#include <QFileInfo>
+#include <QTimer>
+#include <utils/qtcassert.h>
+
+#if Q_BYTE_ORDER == Q_LITTLE_ENDIAN
+#define SET_NATIVE_BYTE_ORDER(x) x.setByteOrder(QDataStream::LittleEndian)
+#else
+#define SET_NATIVE_BYTE_ORDER(x) x.setByteOrder(QDataStream::BigEndian)
+#endif
+
+namespace Debugger {
+namespace Internal {
+
+IPCEngineHost::IPCEngineHost (const DebuggerStartParameters &startParameters)
+    : DebuggerEngine(startParameters)
+    , m_local_guest(0)
+    , m_nextMessagePayloadSize(0)
+    , m_cookie(1)
+    , m_device(0)
+{
+    connect(this, SIGNAL(stateChanged(const DebuggerState &)), this, SLOT(m_stateChanged(const DebuggerState &)));
+}
+
+IPCEngineHost::~IPCEngineHost()
+{
+    delete m_device;
+}
+
+void IPCEngineHost::setLocalGuest(IPCEngineGuest *g)
+{
+    m_local_guest = g;
+}
+
+void IPCEngineHost::setGuestDevice(QIODevice *d)
+{
+    if (m_device) {
+        disconnect(m_device, SIGNAL(readyRead()), this, SLOT(readyRead()));
+        delete m_device;
+    }
+    m_device = d;
+    if (m_device)
+        connect(m_device, SIGNAL(readyRead()), this, SLOT(readyRead()));
+}
+
+void IPCEngineHost::setupEngine()
+{
+    QTC_ASSERT(state() == EngineSetupRequested, qDebug() << state());
+    rpcCall(SetupEngine);
+}
+
+void IPCEngineHost::setupInferior()
+{
+    QTC_ASSERT(state() == InferiorSetupRequested, qDebug() << state());
+    QByteArray p;
+    {
+        QDataStream s(&p, QIODevice::WriteOnly);
+        SET_NATIVE_BYTE_ORDER(s);
+        s << QFileInfo(startParameters().executable).absoluteFilePath();
+        s << startParameters().processArgs;
+        s << startParameters().environment;
+    }
+    rpcCall(SetupInferior, p);
+}
+
+void IPCEngineHost::runEngine()
+{
+    QTC_ASSERT(state() == EngineRunRequested, qDebug() << state());
+    rpcCall(RunEngine);
+}
+
+void IPCEngineHost::shutdownInferior()
+{
+    QTC_ASSERT(state() == InferiorShutdownRequested, qDebug() << state());
+    rpcCall(ShutdownInferior);
+}
+
+void IPCEngineHost::shutdownEngine()
+{
+    rpcCall(ShutdownEngine);
+}
+
+void IPCEngineHost::detachDebugger()
+{
+    rpcCall(DetachDebugger);
+}
+
+void IPCEngineHost::executeStep()
+{
+    rpcCall(ExecuteStep);
+}
+
+void IPCEngineHost::executeStepOut()
+{
+    rpcCall(ExecuteStepOut);
+}
+
+void IPCEngineHost::executeNext()
+{
+    rpcCall(ExecuteNext);
+}
+
+void IPCEngineHost::executeStepI()
+{
+    rpcCall(ExecuteStepI);
+}
+
+void IPCEngineHost::executeNextI()
+{
+    rpcCall(ExecuteNextI);
+}
+
+void IPCEngineHost::continueInferior()
+{
+    QTC_ASSERT(state() == InferiorStopOk, qDebug() << state());
+    resetLocation();
+    rpcCall(ContinueInferior);
+}
+
+void IPCEngineHost::interruptInferior()
+{
+    QTC_ASSERT(state() == InferiorStopRequested, qDebug() << state());
+    rpcCall(InterruptInferior);
+}
+
+void IPCEngineHost::executeRunToLine(const QString &fileName, int lineNumber)
+{
+    QByteArray p;
+    {
+        QDataStream s(&p, QIODevice::WriteOnly);
+        SET_NATIVE_BYTE_ORDER(s);
+        s << fileName;
+        s << quint64(lineNumber);
+    }
+    rpcCall(ExecuteRunToLine, p);
+}
+
+void IPCEngineHost::executeRunToFunction(const QString &functionName)
+{
+    QByteArray p;
+    {
+        QDataStream s(&p, QIODevice::WriteOnly);
+        SET_NATIVE_BYTE_ORDER(s);
+        s << functionName;
+    }
+    rpcCall(ExecuteRunToFunction, p);
+}
+
+void IPCEngineHost::executeJumpToLine(const QString &fileName, int lineNumber)
+{
+    QByteArray p;
+    {
+        QDataStream s(&p, QIODevice::WriteOnly);
+        SET_NATIVE_BYTE_ORDER(s);
+        s << fileName;
+        s << quint64(lineNumber);
+    }
+    rpcCall(ExecuteJumpToLine, p);
+}
+
+
+void IPCEngineHost::activateFrame(int index)
+{
+    resetLocation();
+    QByteArray p;
+    {
+        QDataStream s(&p, QIODevice::WriteOnly);
+        SET_NATIVE_BYTE_ORDER(s);
+        s << quint64(index);
+    }
+    rpcCall(ActivateFrame, p);
+}
+
+void IPCEngineHost::selectThread(int index)
+{
+    resetLocation();
+    Threads threads = threadsHandler()->threads();
+    QTC_ASSERT(index < threads.size(), return);
+    QByteArray p;
+    {
+        QDataStream s(&p, QIODevice::WriteOnly);
+        SET_NATIVE_BYTE_ORDER(s);
+        s << quint64(threads.at(index).id);
+    }
+    rpcCall(SelectThread, p);
+}
+
+void IPCEngineHost::fetchDisassembler(Internal::DisassemblerViewAgent *v)
+{
+    quint64 address = v->frame().address;
+    m_frameToDisassemblerAgent.insert(address, v);
+    QByteArray p;
+    {
+        QDataStream s(&p, QIODevice::WriteOnly);
+        SET_NATIVE_BYTE_ORDER(s);
+        s << address;
+    }
+    rpcCall(Disassemble, p);
+}
+
+
+void IPCEngineHost::addBreakpoint(const Internal::BreakpointData &bp)
+{
+    QByteArray p;
+    {
+        QDataStream s(&p, QIODevice::WriteOnly);
+        SET_NATIVE_BYTE_ORDER(s);
+        s << bp;
+    }
+    rpcCall(AddBreakpoint, p);
+}
+
+void IPCEngineHost::removeBreakpoint(quint64 id)
+{
+    QByteArray p;
+    {
+        QDataStream s(&p, QIODevice::WriteOnly);
+        SET_NATIVE_BYTE_ORDER(s);
+        s << id;
+    }
+    rpcCall(RemoveBreakpoint, p);
+}
+
+void IPCEngineHost::changeBreakpoint(const Internal::BreakpointData &bp)
+{
+    QByteArray p;
+    {
+        QDataStream s(&p, QIODevice::WriteOnly);
+        SET_NATIVE_BYTE_ORDER(s);
+        s << bp;
+    }
+    rpcCall(RemoveBreakpoint, p);
+}
+
+void IPCEngineHost::updateWatchData(const Internal::WatchData &data,
+            const Internal::WatchUpdateFlags &flags)
+{
+    Q_UNUSED(flags);
+    QByteArray p;
+    {
+        QDataStream s(&p, QIODevice::WriteOnly);
+        SET_NATIVE_BYTE_ORDER(s);
+        s << data;
+    }
+    rpcCall(RequestUpdateWatchData, p);
+}
+
+void IPCEngineHost::rpcCallback(quint64 f, QByteArray payload)
+{
+    switch (f) {
+        default:
+            showMessage(QLatin1String("IPC Error: unhandled id in guest to host call"));
+            showMessage(tr("Fatal engine shutdown. Incompatible binary or ipc error."), LogError);
+            showStatusMessage(tr("Fatal engine shutdown. Incompatible binary or ipc error."));
+            notifyEngineSpontaneousShutdown();
+            break;
+        case IPCEngineGuest::NotifyEngineSetupOk:
+            notifyEngineSetupOk();
+            break;
+        case IPCEngineGuest::NotifyEngineSetupFailed:
+            notifyEngineSetupFailed();
+            break;
+        case IPCEngineGuest::NotifyEngineRunFailed:
+            notifyEngineRunFailed();
+            break;
+        case IPCEngineGuest::NotifyInferiorSetupOk:
+            attemptBreakpointSynchronization();
+            notifyInferiorSetupOk();
+            break;
+        case IPCEngineGuest::NotifyInferiorSetupFailed:
+            notifyInferiorSetupFailed();
+            break;
+        case IPCEngineGuest::NotifyEngineRunAndInferiorRunOk:
+            notifyEngineRunAndInferiorRunOk();
+            break;
+        case IPCEngineGuest::NotifyEngineRunAndInferiorStopOk:
+            notifyEngineRunAndInferiorStopOk();
+            break;
+        case IPCEngineGuest::NotifyInferiorRunRequested:
+            notifyInferiorRunRequested();
+            break;
+        case IPCEngineGuest::NotifyInferiorRunOk:
+            notifyInferiorRunOk();
+            break;
+        case IPCEngineGuest::NotifyInferiorRunFailed:
+            notifyInferiorRunFailed();
+            break;
+        case IPCEngineGuest::NotifyInferiorStopOk:
+            notifyInferiorStopOk();
+            break;
+        case IPCEngineGuest::NotifyInferiorSpontaneousStop:
+            notifyInferiorSpontaneousStop();
+            break;
+        case IPCEngineGuest::NotifyInferiorStopFailed:
+            notifyInferiorStopFailed();
+            break;
+        case IPCEngineGuest::NotifyInferiorExited:
+            notifyInferiorExited();
+            break;
+        case IPCEngineGuest::NotifyInferiorShutdownOk:
+            notifyInferiorShutdownOk();
+            break;
+        case IPCEngineGuest::NotifyInferiorShutdownFailed:
+            notifyInferiorShutdownFailed();
+            break;
+        case IPCEngineGuest::NotifyEngineSpontaneousShutdown:
+            notifyEngineSpontaneousShutdown();
+            break;
+        case IPCEngineGuest::NotifyEngineShutdownOk:
+            notifyEngineShutdownOk();
+            break;
+        case IPCEngineGuest::NotifyEngineShutdownFailed:
+            notifyEngineShutdownFailed();
+            break;
+        case IPCEngineGuest::NotifyInferiorIll:
+            notifyInferiorIll();
+            break;
+        case IPCEngineGuest::NotifyEngineIll:
+            notifyEngineIll();
+            break;
+        case IPCEngineGuest::NotifyInferiorPid:
+            {
+                QDataStream s(payload);
+                SET_NATIVE_BYTE_ORDER(s);
+                quint64 pid;
+                s >> pid;
+                notifyInferiorPid(pid);
+            }
+            break;
+        case IPCEngineGuest::ShowStatusMessage:
+            {
+                QDataStream s(payload);
+                SET_NATIVE_BYTE_ORDER(s);
+                QString msg;
+                qint64 timeout;
+                s >> msg;
+                s >> timeout;
+                showStatusMessage(msg, timeout);
+            }
+            break;
+        case IPCEngineGuest::ShowMessage:
+            {
+                QDataStream s(payload);
+                SET_NATIVE_BYTE_ORDER(s);
+                QString msg;
+                qint16 channel;
+                qint64 timeout;
+                s >> msg;
+                s >> channel;
+                s >> timeout;
+                showMessage(msg, channel, timeout);
+            }
+            break;
+        case IPCEngineGuest::CurrentFrameChanged:
+            {
+                QDataStream s(payload);
+                SET_NATIVE_BYTE_ORDER(s);
+                quint64 token;
+                s >> token;
+
+                resetLocation();
+                StackHandler *sh = stackHandler();
+                sh->setCurrentIndex(token);
+                gotoLocation(sh->currentFrame(), true);
+            }
+            break;
+        case IPCEngineGuest::CurrentThreadChanged:
+            {
+                QDataStream s(payload);
+                SET_NATIVE_BYTE_ORDER(s);
+                quint64 token;
+                s >> token;
+                threadsHandler()->setCurrentThreadId(token);
+            }
+            break;
+        case IPCEngineGuest::ListFrames:
+            {
+                QDataStream s(payload);
+                SET_NATIVE_BYTE_ORDER(s);
+                StackFrames frames;
+                s >> frames;
+                stackHandler()->setFrames(frames);
+            }
+            break;
+        case IPCEngineGuest::ListThreads:
+            {
+                QDataStream s(payload);
+                SET_NATIVE_BYTE_ORDER(s);
+                Threads threads;
+                s >> threads;
+                threadsHandler()->setThreads(threads);
+            }
+            break;
+        case IPCEngineGuest::Disassembled:
+            {
+                QDataStream s(payload);
+                SET_NATIVE_BYTE_ORDER(s);
+                quint64 pc;
+                QString da;
+                s >> pc;
+                s >> da;
+                Internal::DisassemblerViewAgent *view = m_frameToDisassemblerAgent.take(pc);
+                if (view)
+                    view->setContents(da);
+            }
+            break;
+        case IPCEngineGuest::UpdateWatchData:
+            {
+                QDataStream s(payload);
+                SET_NATIVE_BYTE_ORDER(s);
+                bool fullCycle;
+                qint64 count;
+                QList<WatchData> wd;
+                s >> fullCycle;
+                s >> count;
+                for (qint64 i = 0; i < count; i++) {
+                    WatchData d;
+                    s >> d;
+                    wd.append(d);
+                }
+                WatchHandler *wh = watchHandler();
+                if (!wh)
+                    break;
+                wh->beginCycle(fullCycle);
+                wh->insertBulkData(wd);
+                wh->endCycle(fullCycle);
+            }
+            break;
+        case IPCEngineGuest::NotifyAddBreakpointOk:
+            {
+                QDataStream s(payload);
+                SET_NATIVE_BYTE_ORDER(s);
+                quint64 id;
+                s >> id;
+                notifyAddBreakpointOk(id);
+            }
+        case IPCEngineGuest::NotifyAddBreakpointFailed:
+            {
+                QDataStream s(payload);
+                SET_NATIVE_BYTE_ORDER(s);
+                quint64 id;
+                s >> id;
+                notifyAddBreakpointFailed(id);
+            }
+        case IPCEngineGuest::NotifyRemoveBreakpointOk:
+            {
+                QDataStream s(payload);
+                SET_NATIVE_BYTE_ORDER(s);
+                quint64 id;
+                s >> id;
+                notifyRemoveBreakpointOk(id);
+            }
+        case IPCEngineGuest::NotifyRemoveBreakpointFailed:
+            {
+                QDataStream s(payload);
+                SET_NATIVE_BYTE_ORDER(s);
+                quint64 id;
+                s >> id;
+                notifyRemoveBreakpointFailed(id);
+            }
+        case IPCEngineGuest::NotifyChangeBreakpointOk:
+            {
+                QDataStream s(payload);
+                SET_NATIVE_BYTE_ORDER(s);
+                quint64 id;
+                s >> id;
+                notifyChangeBreakpointOk(id);
+            }
+        case IPCEngineGuest::NotifyChangeBreakpointFailed:
+            {
+                QDataStream s(payload);
+                SET_NATIVE_BYTE_ORDER(s);
+                quint64 id;
+                s >> id;
+                notifyChangeBreakpointFailed(id);
+            }
+        case IPCEngineGuest::NotifyBreakpointAdjusted:
+            {
+                QDataStream s(payload);
+                SET_NATIVE_BYTE_ORDER(s);
+                BreakpointData d;
+                s >> d;
+                notifyBreakpointAdjusted(d);
+            }
+    }
+}
+
+void IPCEngineHost::m_stateChanged(const DebuggerState &state)
+{
+    QByteArray p;
+    {
+        QDataStream s(&p, QIODevice::WriteOnly);
+        SET_NATIVE_BYTE_ORDER(s);
+        s << (qint64)state;
+    }
+    rpcCall(StateChanged, p);
+
+}
+
+void IPCEngineHost::rpcCall(Function f, QByteArray payload)
+{
+    if (m_local_guest) {
+        QMetaObject::invokeMethod(m_local_guest,
+                "rpcCallback",
+                Qt::QueuedConnection,
+                Q_ARG(quint64, f),
+                Q_ARG(QByteArray, payload));
+    } else if (m_device) {
+        QByteArray header;
+        {
+            QDataStream s(&header, QIODevice::WriteOnly);
+            SET_NATIVE_BYTE_ORDER(s);
+            s << m_cookie++;
+            s << (quint64) f;
+            s << (quint64) payload.size();
+        }
+        m_device->write(header);
+        m_device->write(payload);
+        m_device->putChar('T');
+    }
+}
+
+void IPCEngineHost::readyRead()
+{
+    QDataStream s(m_device);
+    SET_NATIVE_BYTE_ORDER(s);
+    if (!m_nextMessagePayloadSize) {
+        if (quint64(m_device->bytesAvailable ()) < (sizeof(quint64) * 3))
+            return;
+        s >> m_nextMessageCookie;
+        s >> m_nextMessageFunction;
+        s >> m_nextMessagePayloadSize;
+        m_nextMessagePayloadSize += 1; // terminator and "got header" marker
+    }
+
+    quint64 ba = m_device->bytesAvailable();
+    if (ba < m_nextMessagePayloadSize)
+        return;
+
+    QByteArray payload = m_device->read(m_nextMessagePayloadSize - 1);
+
+    char terminator;
+    m_device->getChar(&terminator);
+    if (terminator != 'T') {
+        showStatusMessage(tr("Fatal engine shutdown. Incompatible binary or ipc error."));
+        showMessage(QLatin1String("IPC Error: terminator missing"));
+        notifyEngineSpontaneousShutdown();
+        return;
+    }
+    rpcCallback(m_nextMessageFunction, payload);
+    m_nextMessagePayloadSize = 0;
+    if (quint64(m_device->bytesAvailable()) >= (sizeof(quint64) * 3))
+        QTimer::singleShot(0, this, SLOT(readyRead()));
+}
+
+
+} // namespace Internal
+} // namespace Debugger
+
+
diff --git a/src/plugins/debugger/lldb/ipcenginehost.h b/src/plugins/debugger/lldb/ipcenginehost.h
new file mode 100644 (file)
index 0000000..2a8e49b
--- /dev/null
@@ -0,0 +1,132 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2010 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_IPCENGINE_HOST_H
+#define DEBUGGER_IPCENGINE_HOST_H
+
+#include "debuggerengine.h"
+#include "threadshandler.h"
+#include "stackhandler.h"
+#include "breakhandler.h"
+
+#include <QtCore/QQueue>
+#include <QtCore/QVariant>
+#include <QtCore/QThread>
+
+namespace Debugger {
+namespace Internal {
+
+class IPCEngineGuest;
+class IPCEngineHost : public DebuggerEngine
+{
+    Q_OBJECT
+
+public:
+    explicit IPCEngineHost(const DebuggerStartParameters &startParameters);
+    ~IPCEngineHost();
+
+    // use either one
+    void setLocalGuest(IPCEngineGuest *);
+    void setGuestDevice(QIODevice *);
+
+    enum Function
+    {
+        SetupIPC               = 1,
+        StateChanged           = 2,
+        SetupEngine            = 3,
+        SetupInferior          = 4,
+        RunEngine              = 5,
+        ShutdownInferior       = 6,
+        ShutdownEngine         = 7,
+        DetachDebugger         = 8,
+        ExecuteStep            = 9,
+        ExecuteStepOut         = 10,
+        ExecuteNext            = 11,
+        ExecuteStepI           = 12,
+        ExecuteNextI           = 13,
+        ContinueInferior       = 14,
+        InterruptInferior      = 15,
+        ExecuteRunToLine       = 16,
+        ExecuteRunToFunction   = 17,
+        ExecuteJumpToLine      = 18,
+        ActivateFrame          = 19,
+        SelectThread           = 20,
+        Disassemble            = 21,
+        AddBreakpoint          = 22,
+        RemoveBreakpoint       = 23,
+        ChangeBreakpoint       = 24,
+        RequestUpdateWatchData = 25
+    };
+    Q_ENUMS(Function);
+
+    void setupEngine();
+    void setupInferior();
+    void runEngine();
+    void shutdownInferior();
+    void shutdownEngine();
+    void detachDebugger();
+    void executeStep();
+    void executeStepOut() ;
+    void executeNext();
+    void executeStepI();
+    void executeNextI();
+    void continueInferior();
+    void interruptInferior();
+    void executeRunToLine(const QString &fileName, int lineNumber);
+    void executeRunToFunction(const QString &functionName);
+    void executeJumpToLine(const QString &fileName, int lineNumber);
+    void activateFrame(int index);
+    void selectThread(int index);
+    void fetchDisassembler(Internal::DisassemblerViewAgent *);
+    void addBreakpoint(const Internal::BreakpointData &bp);
+    void removeBreakpoint(quint64 id);
+    void changeBreakpoint(const Internal::BreakpointData &bp);
+    void updateWatchData(const Internal::WatchData &data,
+            const Internal::WatchUpdateFlags &flags = Internal::WatchUpdateFlags());
+
+    void rpcCall(Function f, QByteArray payload = QByteArray());
+public slots:
+    void rpcCallback(quint64 f, QByteArray payload = QByteArray());
+private slots:
+    void m_stateChanged(const DebuggerState &state);
+    void readyRead();
+private:
+    IPCEngineGuest *m_local_guest;
+    quint64 m_nextMessageCookie;
+    quint64 m_nextMessageFunction;
+    quint64 m_nextMessagePayloadSize;
+    quint64 m_cookie;
+    QIODevice *m_device;
+    QHash <quint64, Internal::DisassemblerViewAgent *> m_frameToDisassemblerAgent;
+};
+
+} // namespace Internal
+} // namespace Debugger
+
+#endif // DEBUGGER_LLDBENGINE_H
diff --git a/src/plugins/debugger/lldb/lldbenginehost.cpp b/src/plugins/debugger/lldb/lldbenginehost.cpp
new file mode 100644 (file)
index 0000000..d410c44
--- /dev/null
@@ -0,0 +1,110 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2010 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 "lldbenginehost.h"
+
+#include "debuggeractions.h"
+#include "debuggerconstants.h"
+#include "debuggerdialogs.h"
+#include "debuggerplugin.h"
+#include "debuggerstringutils.h"
+
+#include "breakhandler.h"
+#include "breakpoint.h"
+#include "moduleshandler.h"
+#include "registerhandler.h"
+#include "stackhandler.h"
+#include "watchhandler.h"
+#include "watchutils.h"
+#include "threadshandler.h"
+#include "debuggeragents.h"
+
+#include <utils/qtcassert.h>
+#include <QtCore/QDebug>
+#include <QtCore/QProcess>
+#include <QtCore/QFileInfo>
+#include <QtCore/QThread>
+#include <QtCore/QCoreApplication>
+#include <QtNetwork/QLocalSocket>
+#include <QtNetwork/QLocalServer>
+
+namespace Debugger {
+namespace Internal {
+
+LLDBEngineHost::LLDBEngineHost(const DebuggerStartParameters &startParameters)
+    :IPCEngineHost(startParameters)
+{
+    QLocalServer *s = new QLocalServer(this);
+    s->removeServer (QLatin1String("/tmp/qtcreator-debuggeripc"));
+    s->listen (QLatin1String("/tmp/qtcreator-debuggeripc"));
+
+    m_guestp = new QProcess(this);
+    m_guestp->setProcessChannelMode(QProcess::ForwardedChannels);
+
+    connect(m_guestp, SIGNAL(finished(int, QProcess::ExitStatus)),
+            this, SLOT(finished (int, QProcess::ExitStatus)));
+
+    QString a(qApp->applicationDirPath() + QLatin1String("/../Resources/qtcreator-lldb"));
+    m_guestp->start(a,QStringList());
+
+    if (!m_guestp->waitForStarted()) {
+        showStatusMessage(tr("lldb failed to start"));
+        notifyEngineIll();
+        return;
+    }
+
+    s->waitForNewConnection(-1);
+    QLocalSocket *f = s->nextPendingConnection();
+    s->close(); // wtf race in accept
+    setGuestDevice(f);
+}
+
+LLDBEngineHost::~LLDBEngineHost()
+{
+    disconnect(m_guestp, SIGNAL(finished(int, QProcess::ExitStatus)),
+            this, SLOT(finished (int, QProcess::ExitStatus)));
+    m_guestp->terminate();
+    m_guestp->kill();
+}
+
+void LLDBEngineHost::finished (int, QProcess::ExitStatus)
+{
+    showStatusMessage(QLatin1String("lldb crashed"));
+    notifyEngineIll();
+}
+
+DebuggerEngine *createLLDBEngine(const DebuggerStartParameters &startParameters)
+{
+    return new LLDBEngineHost(startParameters);
+}
+
+} // namespace Internal
+} // namespace Debugger
diff --git a/src/plugins/debugger/lldb/lldbenginehost.h b/src/plugins/debugger/lldb/lldbenginehost.h
new file mode 100644 (file)
index 0000000..47822da
--- /dev/null
@@ -0,0 +1,55 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2010 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_LLDBENGINE_HOST_H
+#define DEBUGGER_LLDBENGINE_HOST_H
+
+#include "ipcenginehost.h"
+
+#include <QtCore/QProcess>
+
+namespace Debugger {
+namespace Internal {
+
+class LLDBEngineHost : public IPCEngineHost
+{
+    Q_OBJECT
+public:
+    explicit LLDBEngineHost(const DebuggerStartParameters &startParameters);
+    ~LLDBEngineHost();
+private:
+    QProcess *m_guestp;
+private slots:
+    void finished (int, QProcess::ExitStatus);
+};
+
+} // namespace Internal
+} // namespace Debugger
+
+#endif // DEBUGGER_LLDBENGINE_H
diff --git a/src/plugins/debugger/lldb/lldbhost.pri b/src/plugins/debugger/lldb/lldbhost.pri
new file mode 100644 (file)
index 0000000..e2f63b0
--- /dev/null
@@ -0,0 +1,13 @@
+HEADERS += $$PWD/ipcenginehost.h \
+           $$PWD/lldbenginehost.h
+
+SOURCES +=  $$PWD/ipcenginehost.cpp \
+            $$PWD/lldbenginehost.cpp
+
+INCLUDEPATH+=
+
+DEFINES += IPC_STANDALONE_HOST
+
+FORMS +=
+
+RESOURCES +=