Commit c0da255a authored by Arvid Ephraim Picciani's avatar Arvid Ephraim Picciani
Browse files

Experimental lldb engine host

parent fce92386
......@@ -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
......
......@@ -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
......
......@@ -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;
......
/**************************************************************************
**
** 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</