From bfdeca4948bc344fb857b0c07e49928cae88deb3 Mon Sep 17 00:00:00 2001 From: hjk Date: Wed, 20 Feb 2013 11:29:58 +0100 Subject: Debugger: Rename lldb to lldblib This is the approach directly linking to the lldb library. Change-Id: I5d51ad59d8292b46539a55da8e23918fb7de9a92 Reviewed-by: hjk --- src/plugins/debugger/debugger.pro | 2 +- src/plugins/debugger/debuggerrunner.cpp | 2 +- src/plugins/debugger/lldb/guest/README | 31 - .../debugger/lldb/guest/lldbengineguest.cpp | 761 --------------------- src/plugins/debugger/lldb/guest/lldbengineguest.h | 136 ---- src/plugins/debugger/lldb/guest/main.cpp | 151 ---- .../debugger/lldb/guest/qtcreator-lldb.plist | 21 - src/plugins/debugger/lldb/guest/qtcreator-lldb.pri | 2 - src/plugins/debugger/lldb/guest/qtcreator-lldb.pro | 61 -- src/plugins/debugger/lldb/ipcengineguest.cpp | 637 ----------------- src/plugins/debugger/lldb/ipcengineguest.h | 191 ------ src/plugins/debugger/lldb/ipcenginehost.cpp | 661 ------------------ src/plugins/debugger/lldb/ipcenginehost.h | 140 ---- src/plugins/debugger/lldb/lldbenginehost.cpp | 232 ------- src/plugins/debugger/lldb/lldbenginehost.h | 88 --- src/plugins/debugger/lldb/lldbhost.pri | 20 - src/plugins/debugger/lldb/lldboptionspage.cpp | 109 --- src/plugins/debugger/lldb/lldboptionspage.h | 80 --- src/plugins/debugger/lldb/lldboptionspagewidget.ui | 59 -- src/plugins/debugger/lldblib/guest/README | 31 + .../debugger/lldblib/guest/lldbengineguest.cpp | 761 +++++++++++++++++++++ .../debugger/lldblib/guest/lldbengineguest.h | 136 ++++ src/plugins/debugger/lldblib/guest/main.cpp | 151 ++++ .../debugger/lldblib/guest/qtcreator-lldb.plist | 21 + .../debugger/lldblib/guest/qtcreator-lldb.pri | 2 + .../debugger/lldblib/guest/qtcreator-lldb.pro | 61 ++ src/plugins/debugger/lldblib/ipcengineguest.cpp | 637 +++++++++++++++++ src/plugins/debugger/lldblib/ipcengineguest.h | 191 ++++++ src/plugins/debugger/lldblib/ipcenginehost.cpp | 661 ++++++++++++++++++ src/plugins/debugger/lldblib/ipcenginehost.h | 140 ++++ src/plugins/debugger/lldblib/lldbenginehost.cpp | 232 +++++++ src/plugins/debugger/lldblib/lldbenginehost.h | 88 +++ src/plugins/debugger/lldblib/lldbhost.pri | 20 + src/plugins/debugger/lldblib/lldboptionspage.cpp | 109 +++ src/plugins/debugger/lldblib/lldboptionspage.h | 80 +++ .../debugger/lldblib/lldboptionspagewidget.ui | 59 ++ 36 files changed, 3382 insertions(+), 3382 deletions(-) delete mode 100644 src/plugins/debugger/lldb/guest/README delete mode 100644 src/plugins/debugger/lldb/guest/lldbengineguest.cpp delete mode 100644 src/plugins/debugger/lldb/guest/lldbengineguest.h delete mode 100644 src/plugins/debugger/lldb/guest/main.cpp delete mode 100644 src/plugins/debugger/lldb/guest/qtcreator-lldb.plist delete mode 100644 src/plugins/debugger/lldb/guest/qtcreator-lldb.pri delete mode 100644 src/plugins/debugger/lldb/guest/qtcreator-lldb.pro delete mode 100644 src/plugins/debugger/lldb/ipcengineguest.cpp delete mode 100644 src/plugins/debugger/lldb/ipcengineguest.h delete mode 100644 src/plugins/debugger/lldb/ipcenginehost.cpp delete mode 100644 src/plugins/debugger/lldb/ipcenginehost.h delete mode 100644 src/plugins/debugger/lldb/lldbenginehost.cpp delete mode 100644 src/plugins/debugger/lldb/lldbenginehost.h delete mode 100644 src/plugins/debugger/lldb/lldbhost.pri delete mode 100644 src/plugins/debugger/lldb/lldboptionspage.cpp delete mode 100644 src/plugins/debugger/lldb/lldboptionspage.h delete mode 100644 src/plugins/debugger/lldb/lldboptionspagewidget.ui create mode 100644 src/plugins/debugger/lldblib/guest/README create mode 100644 src/plugins/debugger/lldblib/guest/lldbengineguest.cpp create mode 100644 src/plugins/debugger/lldblib/guest/lldbengineguest.h create mode 100644 src/plugins/debugger/lldblib/guest/main.cpp create mode 100644 src/plugins/debugger/lldblib/guest/qtcreator-lldb.plist create mode 100644 src/plugins/debugger/lldblib/guest/qtcreator-lldb.pri create mode 100644 src/plugins/debugger/lldblib/guest/qtcreator-lldb.pro create mode 100644 src/plugins/debugger/lldblib/ipcengineguest.cpp create mode 100644 src/plugins/debugger/lldblib/ipcengineguest.h create mode 100644 src/plugins/debugger/lldblib/ipcenginehost.cpp create mode 100644 src/plugins/debugger/lldblib/ipcenginehost.h create mode 100644 src/plugins/debugger/lldblib/lldbenginehost.cpp create mode 100644 src/plugins/debugger/lldblib/lldbenginehost.h create mode 100644 src/plugins/debugger/lldblib/lldbhost.pri create mode 100644 src/plugins/debugger/lldblib/lldboptionspage.cpp create mode 100644 src/plugins/debugger/lldblib/lldboptionspage.h create mode 100644 src/plugins/debugger/lldblib/lldboptionspagewidget.ui (limited to 'src') diff --git a/src/plugins/debugger/debugger.pro b/src/plugins/debugger/debugger.pro index 0ca196b27f..41531388a5 100644 --- a/src/plugins/debugger/debugger.pro +++ b/src/plugins/debugger/debugger.pro @@ -147,7 +147,7 @@ include(cdb/cdb.pri) include(gdb/gdb.pri) include(script/script.pri) include(pdb/pdb.pri) -include(lldb/lldbhost.pri) +include(lldblib/lldbhost.pri) include(qml/qml.pri) include(namedemangler/namedemangler.pri) diff --git a/src/plugins/debugger/debuggerrunner.cpp b/src/plugins/debugger/debuggerrunner.cpp index cac11d0ff7..bfe8ceae8e 100644 --- a/src/plugins/debugger/debuggerrunner.cpp +++ b/src/plugins/debugger/debuggerrunner.cpp @@ -39,7 +39,7 @@ #include "debuggerstringutils.h" #include "debuggerstartparameters.h" #include "debuggerkitinformation.h" -#include "lldb/lldbenginehost.h" +#include "lldblib/lldbenginehost.h" #include "debuggertooltipmanager.h" #ifdef Q_OS_WIN diff --git a/src/plugins/debugger/lldb/guest/README b/src/plugins/debugger/lldb/guest/README deleted file mode 100644 index be9d4fbee7..0000000000 --- a/src/plugins/debugger/lldb/guest/README +++ /dev/null @@ -1,31 +0,0 @@ -LLDB Guest Engine - -You can use the LLDB debugger from the LLVM project with the Qt Creator debugger -plugin on Mac OS. - -For the Qt Creator build to pick up the LLDB Guest Engine, -you must download the LLDB debugger and configure it -to be included in the Qt Creator build. - -To debug an application, Qt Creator must access the memory of the application. -On Mac OS X, this requires code signing. - -To enable LLDB debugger support in Qt Creator: - -1. To download the LLDB debugger, enter the following command: - svn co http://llvm.org/svn/llvm-project/lldb/trunk lldb - -2. To sign the code, follow the instructions in lldb/docs/code-signing.txt. - -3. To open LLDB in Xcode for building, enter the following command: - open lldb.xcodeproj - then select the Release target and press the build button. - -4. In Xcode, press the build button. - -5. type the following to have the qt creator build system find your lldb build: - export WITH_LLDB=/path/to/lldb - -6. To rebuild Qt Creator, change back to the top level directory of - the Qt Creator source, and enter the following command: - qmake -r && make diff --git a/src/plugins/debugger/lldb/guest/lldbengineguest.cpp b/src/plugins/debugger/lldb/guest/lldbengineguest.cpp deleted file mode 100644 index 312a6cb457..0000000000 --- a/src/plugins/debugger/lldb/guest/lldbengineguest.cpp +++ /dev/null @@ -1,761 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/legal -** -** This file is part of Qt Creator. -** -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and Digia. For licensing terms and -** conditions see http://qt.digia.com/licensing. For further information -** use the contact form at http://qt.digia.com/contact-us. -** -** 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. -** -** In addition, as a special exception, Digia gives you certain additional -** rights. These rights are described in the Digia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -****************************************************************************/ - -#define QT_NO_CAST_FROM_ASCII - -#include "lldbengineguest.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 -#include -#include -#include -#include -#include - -#include - -#define DEBUG_FUNC_ENTER \ - showMessage(QString(QLatin1String("LLDB guest engine: %1 ")) \ - .arg(QLatin1String(Q_FUNC_INFO))); \ - qDebug("%s", Q_FUNC_INFO) - -#define SYNC_INFERIOR_OR(x) if (m_running) { x; } - - -namespace Debugger { -namespace Internal { - -void LldbEventListener::listen(lldb::SBListener *listener) -{ - while (true) { - lldb::SBEvent event; - if (listener->WaitForEvent(1000, event)) - emit lldbEvent(&event); - } -} - -LldbEngineGuest::LldbEngineGuest() - : IPCEngineGuest() - , m_running (false) - , m_worker (new LldbEventListener) - , m_lldb (new lldb::SBDebugger) - , m_target (new lldb::SBTarget) - , m_process (new lldb::SBProcess) - , m_listener(new lldb::SBListener("bla")) - , m_relistFrames (false) -#if defined(HAVE_LLDB_PRIVATE) - , py (new PythonLLDBToGdbMiHack) -#endif -{ - qRegisterMetaType("lldb::SBListener *"); - qRegisterMetaType("lldb::SBEvent *"); - - m_worker->moveToThread(&m_wThread); - connect(m_worker, SIGNAL(lldbEvent(lldb::SBEvent*)), this, - SLOT(lldbEvent(lldb::SBEvent*)), Qt::BlockingQueuedConnection); - m_wThread.start(); - setObjectName(QLatin1String("LLDBEngineGuest")); -} - -LldbEngineGuest::~LldbEngineGuest() -{ - delete m_lldb; - delete m_target; - delete m_process; - delete m_listener; -} - - -void LldbEngineGuest::nuke() -{ - ::exit(4); -} - -void LldbEngineGuest::setupEngine() -{ - DEBUG_FUNC_ENTER; - - lldb::SBDebugger::Initialize(); - - *m_lldb = lldb::SBDebugger::Create(); - m_lldb->Initialize(); - if (m_lldb->IsValid()) - notifyEngineSetupOk(); - else - notifyEngineSetupFailed(); - -} - -void LldbEngineGuest::setupInferior(const QString &executable, - const QStringList &args, const QStringList &env) -{ - DEBUG_FUNC_ENTER; - - foreach (const QString &s, args) { - m_arguments.append(s.toLocal8Bit()); - } - foreach (const QString &s, env) { - m_environment.append(s.toLocal8Bit()); - } - - qDebug("creating target for %s", executable.toLocal8Bit().data()); - showStatusMessage(QLatin1String("starting ") + executable); - *m_target = m_lldb->CreateTarget(executable.toLocal8Bit().data()); - if (!m_target->IsValid()) { - notifyInferiorSetupFailed(); - return; - } - DEBUG_FUNC_ENTER; - - const char **argp = new const char *[m_arguments.count() + 1]; - argp[m_arguments.count()] = 0; - for (int i = 0; i < m_arguments.count(); i++) { - argp[i] = m_arguments[i].data(); - } - - const char **envp = new const char *[m_environment.count() + 1]; - envp[m_environment.count()] = 0; - for (int i = 0; i < m_environment.count(); i++) { - envp[i] = m_environment[i].data(); - } - lldb::SBError err; - *m_process = m_target->Launch(argp, envp, NULL, NULL, true, err); - - if (!err.Success()) { - showMessage(QString::fromLocal8Bit(err.GetCString())); - qDebug() << err.GetCString(); - notifyInferiorSetupFailed(); - } - - /* - * note, the actual string ptrs are still valid. They are in m_environment. - * They probably leak. Considered the marvelous API, there is not much we can do - */ - delete [] envp; - - if (!m_process->IsValid()) - notifyEngineRunFailed(); - QTC_ASSERT(m_listener->IsValid(), qDebug() << false); - m_listener->StartListeningForEvents(m_process->GetBroadcaster(), UINT32_MAX); - QMetaObject::invokeMethod(m_worker, "listen", Qt::QueuedConnection, - Q_ARG(lldb::SBListener *, m_listener)); - notifyInferiorSetupOk(); -} - -void LldbEngineGuest::runEngine() -{ - DEBUG_FUNC_ENTER; - m_process->Continue(); -} - -void LldbEngineGuest::shutdownInferior() -{ - DEBUG_FUNC_ENTER; - m_process->Kill(); -} - -void LldbEngineGuest::shutdownEngine() -{ - DEBUG_FUNC_ENTER; - m_currentFrame = lldb::SBFrame(); - m_currentThread = lldb::SBThread(); - m_breakpoints.clear(); - m_localesCache.clear(); - - /* - * this leaks. However, Terminate is broken and lldb leaks anyway - * We should kill the engine guest process - */ - - *m_lldb = lldb::SBDebugger(); - // leakd.Terminate(); - notifyEngineShutdownOk(); -} - -void LldbEngineGuest::detachDebugger() -{ - DEBUG_FUNC_ENTER; -} - -void LldbEngineGuest::executeStep() -{ - DEBUG_FUNC_ENTER; - - if (!m_currentThread.IsValid()) - return; - m_currentThread.StepInto(); -} - -void LldbEngineGuest::executeStepOut() -{ - DEBUG_FUNC_ENTER; - - if (!m_currentThread.IsValid()) - return; - m_currentThread.StepOut(); -} - -void LldbEngineGuest::executeNext() -{ - DEBUG_FUNC_ENTER; - - if (!m_currentThread.IsValid()) - return; - m_currentThread.StepOver(); -} - -void LldbEngineGuest::executeStepI() -{ - DEBUG_FUNC_ENTER; - - if (!m_currentThread.IsValid()) - return; - m_currentThread.StepInstruction(false); -} - -void LldbEngineGuest::executeNextI() -{ - DEBUG_FUNC_ENTER; - - if (!m_currentThread.IsValid()) - return; - m_currentThread.StepInstruction(true); -} - -void LldbEngineGuest::continueInferior() -{ - DEBUG_FUNC_ENTER; - - notifyInferiorRunRequested(); - m_process->Continue(); - showStatusMessage(QLatin1String("resuming inferior")); -} -void LldbEngineGuest::interruptInferior() -{ - DEBUG_FUNC_ENTER; - - m_process->Stop(); - notifyInferiorStopOk(); - m_relistFrames = true; - updateThreads(); -} - -void LldbEngineGuest::executeRunToLine(const ContextData &data); -{ - DEBUG_FUNC_ENTER; - - // TODO - Q_UNUSED(data); -} - -void LldbEngineGuest::executeRunToFunction(const QString &functionName) -{ - DEBUG_FUNC_ENTER; - - // TODO - Q_UNUSED(functionName); -} -void LldbEngineGuest::executeJumpToLine(const ContextData &data); -{ - DEBUG_FUNC_ENTER; - - // TODO - Q_UNUSED(data); -} - -void LldbEngineGuest::activateFrame(qint64 token) -{ - DEBUG_FUNC_ENTER; - SYNC_INFERIOR_OR(showMessage(QLatin1String( - "activateFrame called while inferior running")); return); - - currentFrameChanged(token); - m_localesCache.clear(); - - lldb::SBFrame fr = m_currentThread.GetFrameAtIndex(token); - m_currentFrame = fr; - lldb::SBSymbolContext context = fr.GetSymbolContext(lldb::eSymbolContextEverything); - lldb::SBValueList values = fr.GetVariables(true, true, false, true); - QList wd; - QByteArray iname = "local"; - for (uint i = 0; i < values.GetSize(); i++) { - lldb::SBValue v = values.GetValueAtIndex(i); - if (!v.IsInScope(fr)) - continue; - getWatchDataR(v, 1, iname, wd); - } - updateWatchData(true, wd); -} - -void LldbEngineGuest::requestUpdateWatchData(const Internal::WatchData &data, - const Internal::WatchUpdateFlags &) -{ - DEBUG_FUNC_ENTER; - SYNC_INFERIOR_OR(return); - - lldb::SBValue v = m_localesCache.value(QString::fromUtf8(data.iname)); - QList wd; - for (uint j = 0; j < v.GetNumChildren(); j++) { - lldb::SBValue vv = v.GetChildAtIndex(j); - getWatchDataR(vv, 1, data.iname, wd); - } - updateWatchData(false, wd); -} - -void LldbEngineGuest::getWatchDataR(lldb::SBValue v, int level, - const QByteArray &p_iname, QList &wd) -{ - QByteArray iname = p_iname + '.' + QByteArray(v.GetName()); - m_localesCache.insert(QString::fromLocal8Bit(iname), v); - -#if defined(HAVE_LLDB_PRIVATE) - wd += py->expand(p_iname, v, m_currentFrame, *m_process); -#else - WatchData d; - d.name = QString::fromLocal8Bit(v.GetName()); - d.iname = iname; - d.type = QByteArray(v.GetTypeName()).trimmed(); - d.value = (QString::fromLocal8Bit(v.GetValue(m_currentFrame))); - d.hasChildren = v.GetNumChildren(); - d.state = WatchData::State(0); - wd.append(d); -#endif - - if (--level > 0) { - for (uint j = 0; j < v.GetNumChildren(); j++) { - lldb::SBValue vv = v.GetChildAtIndex(j); - getWatchDataR(vv, level, iname, wd); - } - } -} - -void LldbEngineGuest::disassemble(quint64 pc) -{ - DEBUG_FUNC_ENTER; - SYNC_INFERIOR_OR(return); - - if (!m_currentThread.IsValid()) - return; - for (uint j = 0; j < m_currentThread.GetNumFrames(); j++) { - lldb::SBFrame fr = m_currentThread.GetFrameAtIndex(j); - if (pc == fr.GetPCAddress().GetLoadAddress(*m_target)) { - QString linesStr = QString::fromLocal8Bit(fr.Disassemble()); - DisassemblerLines lines; - foreach (const QString &lineStr, linesStr.split(QLatin1Char('\n'))) { - lines.appendLine(DisassemblerLine(lineStr)); - } - disassembled(pc, lines); - } - } -} -void LldbEngineGuest::fetchFrameSource(qint64 frame) -{ - QFile f(m_frame_to_file.value(frame)); - f.open(QFile::ReadOnly); - frameSourceFetched(frame, QFileInfo(m_frame_to_file.value(frame)).fileName() - , QString::fromLocal8Bit(f.readAll())); -} - -void LldbEngineGuest::addBreakpoint(BreakpointId id, - const Internal::BreakpointParameters &bp_) -{ - DEBUG_FUNC_ENTER; - SYNC_INFERIOR_OR(notifyAddBreakpointFailed(id); return); - - Internal::BreakpointParameters bp(bp_); - - lldb::SBBreakpoint llbp = m_target->BreakpointCreateByLocation( - bp.fileName.toLocal8Bit().constData(), bp.lineNumber); - if (llbp.IsValid()) { - m_breakpoints.insert(id, llbp); - - llbp.SetIgnoreCount(bp.ignoreCount); - bp.ignoreCount = llbp.GetIgnoreCount(); - bp.enabled = llbp.IsEnabled(); - - lldb::SBBreakpointLocation location = llbp.GetLocationAtIndex(0); - if (location.IsValid()) { - bp.address = location.GetLoadAddress(); - - // FIXME get those from lldb - bp.lineNumber = bp.lineNumber; - bp.fileName = bp.fileName; - notifyAddBreakpointOk(id); - showMessage(QLatin1String("[BB] ok.")); - notifyBreakpointAdjusted(id, bp); - } else { - m_breakpoints.take(id); - showMessage(QLatin1String("[BB] failed. cant resolve yet")); -// notifyAddBreakpointFailed(id); -// notifyAddBreakpointOk(id); - } - } else { - showMessage(QLatin1String("[BB] failed. dunno.")); - notifyAddBreakpointFailed(id); - } -} - -void LldbEngineGuest::removeBreakpoint(BreakpointId id) -{ - DEBUG_FUNC_ENTER; - SYNC_INFERIOR_OR(notifyRemoveBreakpointFailed(id); return); - - lldb::SBBreakpoint llbp = m_breakpoints.take(id); - llbp.SetEnabled(false); - notifyRemoveBreakpointOk(id); -} - -void LldbEngineGuest::changeBreakpoint(BreakpointId id, - const Internal::BreakpointParameters &bp) -{ - DEBUG_FUNC_ENTER; - - // TODO - Q_UNUSED(id); - Q_UNUSED(bp); -} - -void LldbEngineGuest::selectThread(qint64 token) -{ - DEBUG_FUNC_ENTER; - SYNC_INFERIOR_OR(return); - - m_frame_to_file.clear(); - for (uint i = 0; i < m_process->GetNumThreads(); i++) { - lldb::SBThread t = m_process->GetThreadAtIndex(i); - if (t.GetThreadID() == token) { - m_currentThread = t; - StackFrames frames; - int firstResolvableFrame = -1; - for (uint j = 0; j < t.GetNumFrames(); j++) { - lldb::SBFrame fr = t.GetFrameAtIndex(j); - if (!fr.IsValid()) { - qDebug("warning: frame %i is garbage", j); - continue; - } - lldb::SBSymbolContext context = - fr.GetSymbolContext(lldb::eSymbolContextEverything); - lldb::SBSymbol sym = fr.GetSymbol(); - lldb::SBFunction func = fr.GetFunction(); - lldb::SBCompileUnit tu = fr.GetCompileUnit(); - lldb::SBModule module = fr.GetModule(); - lldb::SBBlock block = fr.GetBlock(); - lldb::SBBlock fblock = fr.GetFrameBlock(); - lldb::SBLineEntry le = fr.GetLineEntry(); - lldb::SBValueList values = fr.GetVariables(true, true, true, false); -#if 0 - qDebug()<<"\tframe "<\n" << fr.Disassemble() << "<--"; -#endif - - QString sourceFile; - QString sourceFilePath; - int lineNumber = 0; - if (le.IsValid()) { - lineNumber = le.GetLine(); - if (le.GetFileSpec().IsValid()) { - sourceFile = QString::fromLocal8Bit(le.GetFileSpec().GetFilename()); - sourceFilePath = QString::fromLocal8Bit(le.GetFileSpec().GetDirectory()) - + QLatin1String("/") + sourceFile; - if (firstResolvableFrame < 0) - firstResolvableFrame = j; - } - } - sourceFilePath = QFileInfo(sourceFilePath).canonicalFilePath(); - - QString functionName; - if (func.IsValid()) - functionName = QString::fromLocal8Bit(func.GetName()); - else - functionName = QString::fromLocal8Bit(sym.GetName()); - - StackFrame frame; - frame.level = fr.GetFrameID(); - if (func.IsValid()) - frame.function = QString::fromLocal8Bit(func.GetName()); - else - frame.function = QString::fromLocal8Bit(sym.GetName()); - frame.from = QString::fromLocal8Bit(module.GetFileSpec().GetFilename()); - frame.address = fr.GetPCAddress().GetLoadAddress(*m_target); - frame.line = lineNumber; - frame.file = sourceFilePath; - frame.usable = QFileInfo(frame.file).isReadable(); - frames.append(frame); - m_frame_to_file.insert(j, frame.file); - } - currentThreadChanged(token); - listFrames(frames); - activateFrame(firstResolvableFrame > -1 ? firstResolvableFrame : 0); - return; - } - } -} - -void LldbEngineGuest::updateThreads() -{ - DEBUG_FUNC_ENTER; - SYNC_INFERIOR_OR(return); - - /* There is no way to find the StopReason of a _process_ - * We try to emulate gdb here, by assuming there must be exactly one 'guilty' thread. - * However, if there are no threads at all, it must be that the process - * no longer exists. Let's tear down the whole session. - */ - if (m_process->GetNumThreads() < 1) { - notifyEngineSpontaneousShutdown(); - m_process->Kill(); - m_process->Destroy(); - } - - Threads threads; - for (uint i = 0; i < m_process->GetNumThreads(); i++) { - lldb::SBThread t = m_process->GetThreadAtIndex(i); - if (!t.IsValid()) { - qDebug("warning: thread %i is garbage", i); - continue; - } - ThreadData thread; - thread.id = t.GetThreadID(); - thread.targetId = QString::number(t.GetThreadID()); - thread.core.clear(); - thread.state = QString::number(t.GetStopReason()); - - switch (t.GetStopReason()) { - case lldb::eStopReasonInvalid: - case lldb::eStopReasonNone: - case lldb::eStopReasonTrace: - thread.state = QLatin1String("running"); - break; - case lldb::eStopReasonBreakpoint: - case lldb::eStopReasonWatchpoint: - showStatusMessage(QLatin1String("hit breakpoint")); - thread.state = QLatin1String("hit breakpoint"); - if (m_currentThread.GetThreadID() != t.GetThreadID()) { - m_currentThread = t; - currentThreadChanged(t.GetThreadID()); - m_relistFrames = true; - } - break; - case lldb::eStopReasonSignal: - showStatusMessage(QLatin1String("stopped")); - thread.state = QLatin1String("stopped"); - if (m_currentThread.GetThreadID() != t.GetThreadID()) { - m_currentThread = t; - currentThreadChanged(t.GetThreadID()); - m_relistFrames = true; - } - break; - case lldb::eStopReasonException: - showStatusMessage(QLatin1String("application crashed.")); - thread.state = QLatin1String("crashed"); - if (m_currentThread.GetThreadID() != t.GetThreadID()) { - m_currentThread = t; - currentThreadChanged(t.GetThreadID()); - m_relistFrames = true; - } - break; - case lldb::eStopReasonPlanComplete: - thread.state = QLatin1String("crazy things happened"); - break; - }; - - thread.lineNumber = 0; - thread.name = QString::fromLocal8Bit(t.GetName()); - - lldb::SBFrame fr = t.GetFrameAtIndex(0); - if (!fr.IsValid()) { - qDebug("warning: frame 0 is garbage"); - continue; - } - lldb::SBSymbolContext context = fr.GetSymbolContext(lldb::eSymbolContextEverything); - lldb::SBSymbol sym = fr.GetSymbol(); - lldb::SBFunction func = fr.GetFunction(); - lldb::SBLineEntry le = fr.GetLineEntry(); - QString sourceFile; - QString sourceFilePath; - int lineNumber = 0; - if (le.IsValid()) { - lineNumber = le.GetLine(); - if (le.GetFileSpec().IsValid()) { - sourceFile = QString::fromLocal8Bit(le.GetFileSpec().GetFilename()); - sourceFilePath = QString::fromLocal8Bit(le.GetFileSpec().GetDirectory()) - + QLatin1String("/") + sourceFile; - } - } - QString functionName; - if (func.IsValid()) - functionName = QString::fromLocal8Bit(func.GetName()); - else - functionName = QString::fromLocal8Bit(sym.GetName()); - - lldb::SBValueList values = fr.GetVariables(true, true, false, false); - thread.fileName = sourceFile; - thread.function = functionName; - thread.address = fr.GetPCAddress().GetLoadAddress(*m_target); - thread.lineNumber = lineNumber; - threads.append(thread); - } - listThreads(threads); - if (m_relistFrames) { - selectThread(m_currentThread.GetThreadID()); - m_relistFrames = false; - } -} - -void LldbEngineGuest::lldbEvent(lldb::SBEvent *ev) -{ - qDebug() << "lldbevent" << ev->GetType() << - m_process->GetState() << (int)state(); - - uint32_t etype = ev->GetType(); - switch (etype) { - // ProcessEvent - case 1: - switch (m_process->GetState()) { - case lldb::eStateRunning: // 5 - if (!m_running) - m_running = true; - notifyInferiorPid(m_process->GetProcessID()); - switch (state()) { - case EngineRunRequested: - notifyEngineRunAndInferiorRunOk(); - break; - case InferiorRunRequested: - notifyInferiorRunOk(); - break; - case InferiorStopOk: - notifyInferiorRunRequested(); - notifyInferiorRunOk(); - break; - default: - break; - } - break; - case lldb::eStateExited: // 9 - if (m_running) - m_running = false; - switch (state()) { - case InferiorShutdownRequested: - notifyInferiorShutdownOk(); - break; - case InferiorRunOk: - m_relistFrames = true; - updateThreads(); - notifyEngineSpontaneousShutdown(); - m_process->Kill(); - m_process->Destroy(); - break; - default: - updateThreads(); - break; - } - break; - case lldb::eStateStopped: // 4 - if (m_running) - m_running = false; - switch (state()) { - case InferiorShutdownRequested: - notifyInferiorShutdownOk(); - break; - case InferiorRunOk: - m_relistFrames = true; - updateThreads(); - notifyInferiorSpontaneousStop(); - // fall - default: - m_relistFrames = true; - updateThreads(); - break; - } - break; - case lldb::eStateCrashed: // 7 - if (m_running) - m_running = false; - switch (state()) { - case InferiorShutdownRequested: - notifyInferiorShutdownOk(); - break; - case InferiorRunOk: - m_relistFrames = true; - updateThreads(); - notifyInferiorSpontaneousStop(); - break; - default: - break; - } - break; - default: - qDebug("unexpected ProcessEvent"); - break; - } - break;; - default: - break;; - }; -} - - -} // namespace Internal -} // namespace Debugger diff --git a/src/plugins/debugger/lldb/guest/lldbengineguest.h b/src/plugins/debugger/lldb/guest/lldbengineguest.h deleted file mode 100644 index c11ac3f0a3..0000000000 --- a/src/plugins/debugger/lldb/guest/lldbengineguest.h +++ /dev/null @@ -1,136 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/legal -** -** This file is part of Qt Creator. -** -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and Digia. For licensing terms and -** conditions see http://qt.digia.com/licensing. For further information -** use the contact form at http://qt.digia.com/contact-us. -** -** 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. -** -** In addition, as a special exception, Digia gives you certain additional -** rights. These rights are described in the Digia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -****************************************************************************/ - -#ifndef DEBUGGER_LLDBENGINE_GUEST_H -#define DEBUGGER_LLDBENGINE_GUEST_H - -#include "ipcengineguest.h" - -#include -#include -#include -#include - -#include - -#if defined(HAVE_LLDB_PRIVATE) -#include "pygdbmiemu.h" -#endif - -Q_DECLARE_METATYPE (lldb::SBListener *) -Q_DECLARE_METATYPE (lldb::SBEvent *) - -namespace Debugger { -namespace Internal { - -class LldbEventListener : public QObject -{ -Q_OBJECT -public slots: - void listen(lldb::SBListener *listener); -signals: - // lldb API uses non thread safe implicit sharing with no explicit copy feature - // additionally the scope is undefined, hence this signal needs to be connected BlockingQueued - // whutever, works for now. - void lldbEvent(lldb::SBEvent *ev); -}; - - -class LldbEngineGuest : public IPCEngineGuest -{ - Q_OBJECT - -public: - explicit LldbEngineGuest(); - ~LldbEngineGuest(); - - void nuke(); - void setupEngine(); - void setupInferior(const QString &executable, const QStringList &arguments, - const QStringList &environment); - 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 ContextData &data); - void executeRunToFunction(const QString &functionName); - void executeJumpToLine(const ContextData &data); - void activateFrame(qint64); - void selectThread(qint64); - void disassemble(quint64 pc); - void addBreakpoint(BreakpointModelId id, const BreakpointParameters &bp); - void removeBreakpoint(BreakpointModelId id); - void changeBreakpoint(BreakpointModelId id, const BreakpointParameters &bp); - void requestUpdateWatchData(const WatchData &data, - const WatchUpdateFlags &flags); - void fetchFrameSource(qint64 frame); - -private: - bool m_running; - - QList m_arguments; - QList m_environment; - QThread m_wThread; - LldbEventListener *m_worker; - lldb::SBDebugger *m_lldb; - lldb::SBTarget *m_target; - lldb::SBProcess *m_process; - lldb::SBListener *m_listener; - - lldb::SBFrame m_currentFrame; - lldb::SBThread m_currentThread; - bool m_relistFrames; - QHash m_localesCache; - QHash m_breakpoints; - QHash m_frame_to_file; - - void updateThreads(); - void getWatchDataR(lldb::SBValue v, int level, - const QByteArray &p_iname, QList &wd); - -#if defined(HAVE_LLDB_PRIVATE) - PythonLLDBToGdbMiHack * py; -#endif - -private slots: - void lldbEvent(lldb::SBEvent *ev); -}; - -} // namespace Internal -} // namespace Debugger - -#endif // DEBUGGER_LLDBENGINE_H -#define SYNC_INFERIOR diff --git a/src/plugins/debugger/lldb/guest/main.cpp b/src/plugins/debugger/lldb/guest/main.cpp deleted file mode 100644 index 9803a490f8..0000000000 --- a/src/plugins/debugger/lldb/guest/main.cpp +++ /dev/null @@ -1,151 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/legal -** -** This file is part of Qt Creator. -** -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and Digia. For licensing terms and -** conditions see http://qt.digia.com/licensing. For further information -** use the contact form at http://qt.digia.com/contact-us. -** -** 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. -** -** In addition, as a special exception, Digia gives you certain additional -** rights. These rights are described in the Digia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -****************************************************************************/ - -#include "lldbengineguest.h" - -#include -#include -#include -#include - -#include - -// #define DO_STDIO_DEBUG 1 -#ifdef DO_STDIO_DEBUG -#define D_STDIO0(x) qDebug(x) -#define D_STDIO1(x,a1) qDebug(x,a1) -#define D_STDIO2(x,a1,a2) qDebug(x,a1,a2) -#define D_STDIO3(x,a1,a2,a3) qDebug(x,a1,a2,a3) -#else -#define D_STDIO0(x) -#define D_STDIO1(x,a1) -#define D_STDIO2(x,a1,a2) -#define D_STDIO3(x,a1,a2,a3) -#endif - -class Stdio : public QIODevice -{ - Q_OBJECT -public: - QSocketNotifier notify; - Stdio() - : QIODevice() - , notify(fileno(stdin), QSocketNotifier::Read) - , buckethead(0) - { - setvbuf(stdin , NULL , _IONBF , 0); - setvbuf(stdout , NULL , _IONBF , 0); - setOpenMode(QIODevice::ReadWrite | QIODevice::Unbuffered); - connect(¬ify, SIGNAL(activated(int)), this, SLOT(activated())); - } - virtual qint64 bytesAvailable () const - { - qint64 r = QIODevice::bytesAvailable(); - foreach (const QByteArray &bucket, buckets) - r += bucket.size(); - r-= buckethead; - return r; - } - - virtual qint64 readData (char * data, qint64 maxSize) - { - D_STDIO1("readData %lli",maxSize); - qint64 size = maxSize; - while (size > 0) { - if (!buckets.size()) { - D_STDIO1("done prematurely with %lli", maxSize - size); - return maxSize - size; - } - QByteArray &bucket = buckets.head(); - if ((size + buckethead) >= bucket.size()) { - int d = bucket.size() - buckethead; - D_STDIO3("read (over bucket) d: %i buckethead: %i bucket.size(): %i", - d, buckethead, bucket.size()); - memcpy(data, bucket.data() + buckethead, d); - data += d; - size -= d; - buckets.dequeue(); - buckethead = 0; - } else { - D_STDIO1("read (in bucket) size: %lli", size); - memcpy(data, bucket.data() + buckethead, size); - data += size; - buckethead += size; - size = 0; - } - } - D_STDIO1("done with %lli",(maxSize - size)); - return maxSize - size; - } - - virtual qint64 writeData (const char * data, qint64 maxSize) - { - return ::write(fileno(stdout), data, maxSize); - } - - QQueue buckets; - int buckethead; - -private slots: - void activated() - { - QByteArray a; - a.resize(1000); - int ret = ::read(fileno(stdin), a.data(), 1000); - if (ret == 0) - ::exit(0); - assert(ret <= 1000); - D_STDIO1("activated %i", ret); - a.resize(ret); - buckets.enqueue(a); - emit readyRead(); - } -}; - -int main(int argc, char **argv) -{ - QCoreApplication app(argc, argv); - qDebug() << "guest engine operational"; - - Debugger::Internal::LldbEngineGuest lldb; - - - Stdio stdio; - lldb.setHostDevice(&stdio); - - return app.exec(); -} - -extern "C" { -extern const unsigned char lldbVersionString[] __attribute__ ((used)) = "@(#)PROGRAM:lldb PROJECT:lldb-26" "\n"; -extern const double lldbVersionNumber __attribute__ ((used)) = (double)26.; -extern const double LLDBVersionNumber __attribute__ ((used)) = (double)26.; -} - -#include "main.moc" diff --git a/src/plugins/debugger/lldb/guest/qtcreator-lldb.plist b/src/plugins/debugger/lldb/guest/qtcreator-lldb.plist deleted file mode 100644 index c0a3b2beaf..0000000000 --- a/src/plugins/debugger/lldb/guest/qtcreator-lldb.plist +++ /dev/null @@ -1,21 +0,0 @@ - - - - - CFBundleDevelopmentRegion - English - CFBundleIdentifier - org.qt-project.qtcreator-lldb - CFBundleInfoDictionaryVersion - 6.0 - CFBundleName - Qt Creator LLDB Guest - CFBundleVersion - 1.0 - SecTaskAccess - - allowed - safe - - - diff --git a/src/plugins/debugger/lldb/guest/qtcreator-lldb.pri b/src/plugins/debugger/lldb/guest/qtcreator-lldb.pri deleted file mode 100644 index f44c3e9c84..0000000000 --- a/src/plugins/debugger/lldb/guest/qtcreator-lldb.pri +++ /dev/null @@ -1,2 +0,0 @@ -WITH_LLDB = $$(WITH_LLDB) -macx: !isEmpty(WITH_LLDB) : SUBDIRS += $$PWD/qtcreator-lldb.pro diff --git a/src/plugins/debugger/lldb/guest/qtcreator-lldb.pro b/src/plugins/debugger/lldb/guest/qtcreator-lldb.pro deleted file mode 100644 index 847e31140c..0000000000 --- a/src/plugins/debugger/lldb/guest/qtcreator-lldb.pro +++ /dev/null @@ -1,61 +0,0 @@ -WITH_LLDB = $$(WITH_LLDB) - -!macx: error (This can only be built on mac) -!exists($${WITH_LLDB}/include/lldb/lldb-enumerations.h): error(please see the README for build instructions) - -QT = core network - -include(../../../../../qtcreator.pri) -TEMPLATE = app -CONFIG -= app_bundle -CONFIG += debug -TARGET = qtcreator-lldb -DEPENDPATH += . .. ../.. ../../.. ../../../../libs -INCLUDEPATH += . .. ../.. ../../.. ../../../../libs -DESTDIR = $$IDE_LIBEXEC_PATH - -MOC_DIR=.tmp -OBJECTS_DIR=.tmp - -HEADERS += ../ipcengineguest.h \ - ../debuggerstreamops.h \ - ../breakpoint.h \ - ../watchdata.h \ - ../stackframe.h \ - ../disassemblerlines.h \ - lldbengineguest.h - -SOURCES += ../ipcengineguest.cpp \ - ../debuggerstreamops.cpp \ - ../breakpoint.cpp \ - ../watchdata.cpp \ - ../stackframe.cpp \ - ../disassemblerlines.cpp \ - lldbengineguest.cpp \ - main.cpp - - -LIBS += -sectcreate __TEXT __info_plist $$PWD/qtcreator-lldb.plist - -POSTL = rm -rf \'$${IDE_LIBEXEC_PATH}/LLDB.framework\' $$escape_expand(\\n\\t) \ - $$QMAKE_COPY_DIR $${WITH_LLDB}/build/Release/* \'$$IDE_LIBEXEC_PATH\' $$escape_expand(\\n\\t) \ - install_name_tool -change '@rpath/LLDB.framework/Versions/A/LLDB' '@executable_path/LLDB.framework/Versions/A/LLDB' $(TARGET) $$escape_expand(\\n\\t) \ - codesign -s lldb_codesign $(TARGET) - -!isEmpty(QMAKE_POST_LINK):QMAKE_POST_LINK = $$escape_expand(\\n\\t)$$QMAKE_POST_LINK -QMAKE_POST_LINK = $$POSTL $$QMAKE_POST_LINK -silent:QMAKE_POST_LINK = @echo signing $@ && $$QMAKE_POST_LINK - -LIBS += -framework Security -framework Python - -DEFINES += __STDC_LIMIT_MACROS __STDC_CONSTANT_MACROS - -INCLUDEPATH += $${WITH_LLDB}/include $${WITH_LLDB}/llvm/include/ -LIBS += -F$${WITH_LLDB}/build/Release -framework LLDB - -# include (lldb.pri) -# DEFINES += HAVE_LLDB_PRIVATE -# HEADERS += pygdbmiemu.h -# SOURCES += pygdbmiemu.cpp - - diff --git a/src/plugins/debugger/lldb/ipcengineguest.cpp b/src/plugins/debugger/lldb/ipcengineguest.cpp deleted file mode 100644 index 50ebae4177..0000000000 --- a/src/plugins/debugger/lldb/ipcengineguest.cpp +++ /dev/null @@ -1,637 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/legal -** -** This file is part of Qt Creator. -** -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and Digia. For licensing terms and -** conditions see http://qt.digia.com/licensing. For further information -** use the contact form at http://qt.digia.com/contact-us. -** -** 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. -** -** In addition, as a special exception, Digia gives you certain additional -** rights. These rights are described in the Digia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -****************************************************************************/ - -#include "ipcengineguest.h" -#include "ipcenginehost.h" -#include "breakpoint.h" -#include "stackframe.h" -#include "threaddata.h" -#include "debuggerstreamops.h" - -#include - -#include - -#include -#include -#include -#include - -#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 *host) -{ - m_local_host = host; -} - -void IPCEngineGuest::setHostDevice(QIODevice *device) -{ - if (m_device) { - disconnect(m_device, SIGNAL(readyRead()), this, SLOT(readyRead())); - delete m_device; - } - m_device = device; - if (m_device) - connect(m_device, SIGNAL(readyRead()), SLOT(readyRead())); -} - -void IPCEngineGuest::rpcCall(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'); - QLocalSocket *sock = qobject_cast(m_device); - if (sock) - sock->flush(); - } -} - -void IPCEngineGuest::readyRead() -{ - if (!m_nextMessagePayloadSize) { - if (quint64(m_device->bytesAvailable()) < 3 * sizeof(quint64)) - 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')) { - qDebug("IPC Error: corrupted frame"); - showMessage(QLatin1String("[guest] IPC Error: corrupted frame"), LogError); - nuke(); - return; - } - payload.chop(1); - rpcCallback(m_nextMessageFunction, payload); - m_nextMessagePayloadSize = 0; - - if (quint64(m_device->bytesAvailable ()) >= 3 * sizeof(quint64)) - QTimer::singleShot(0, this, SLOT(readyRead())); -} - -void IPCEngineGuest::rpcCallback(quint64 f, QByteArray payload) -{ - switch (f) { - default: - qDebug("IPC Error: unhandled id in host to guest call"); - showMessage(QLatin1String("IPC Error: unhandled id in host to guest call"), LogError); - nuke(); - 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); - ContextData data; - s >> data.fileName; - s >> data.lineNumber; - executeRunToLine(data); - } - 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); - ContextData data; - s >> data.fileName; - s >> data.lineNumber; - executeJumpToLine(data); - } - 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); - BreakpointModelId id; - BreakpointParameters d; - s >> id; - s >> d; - addBreakpoint(id, d); - } - break; - case IPCEngineHost::RemoveBreakpoint: - { - QDataStream s(payload); - SET_NATIVE_BYTE_ORDER(s); - BreakpointModelId id; - s >> id; - removeBreakpoint(id); - } - break; - case IPCEngineHost::ChangeBreakpoint: - { - QDataStream s(payload); - SET_NATIVE_BYTE_ORDER(s); - BreakpointModelId id; - BreakpointParameters d; - s >> id; - s >> d; - changeBreakpoint(id, d); - } - break; - case IPCEngineHost::RequestUpdateWatchData: - { - QDataStream s(payload); - SET_NATIVE_BYTE_ORDER(s); - WatchData data; - s >> data; - requestUpdateWatchData(data); - } - break; - case IPCEngineHost::FetchFrameSource: - { - QDataStream s(payload); - SET_NATIVE_BYTE_ORDER(s); - qint64 id; - s >> id; - fetchFrameSource(id); - } - 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 DisassemblerLines &da) -{ - QByteArray p; - { - QDataStream s(&p, QIODevice::WriteOnly); - SET_NATIVE_BYTE_ORDER(s); - s << pc; - s << da; - } - rpcCall(Disassembled, p); -} - -void IPCEngineGuest::notifyAddBreakpointOk(BreakpointModelId id) -{ - QByteArray p; - { - QDataStream s(&p, QIODevice::WriteOnly); - SET_NATIVE_BYTE_ORDER(s); - s << id; - } - rpcCall(NotifyAddBreakpointOk, p); -} - -void IPCEngineGuest::notifyAddBreakpointFailed(BreakpointModelId id) -{ - QByteArray p; - { - QDataStream s(&p, QIODevice::WriteOnly); - SET_NATIVE_BYTE_ORDER(s); - s << id; - } - rpcCall(NotifyAddBreakpointFailed, p); -} - -void IPCEngineGuest::notifyRemoveBreakpointOk(BreakpointModelId id) -{ - QByteArray p; - { - QDataStream s(&p, QIODevice::WriteOnly); - SET_NATIVE_BYTE_ORDER(s); - s << id; - } - rpcCall(NotifyRemoveBreakpointOk, p); -} - -void IPCEngineGuest::notifyRemoveBreakpointFailed(BreakpointModelId id) -{ - QByteArray p; - { - QDataStream s(&p, QIODevice::WriteOnly); - SET_NATIVE_BYTE_ORDER(s); - s << id; - } - rpcCall(NotifyRemoveBreakpointFailed, p); -} - -void IPCEngineGuest::notifyChangeBreakpointOk(BreakpointModelId id) -{ - QByteArray p; - { - QDataStream s(&p, QIODevice::WriteOnly); - SET_NATIVE_BYTE_ORDER(s); - s << id; - } - rpcCall(NotifyChangeBreakpointOk, p); -} - -void IPCEngineGuest::notifyChangeBreakpointFailed(BreakpointModelId id) -{ - QByteArray p; - { - QDataStream s(&p, QIODevice::WriteOnly); - SET_NATIVE_BYTE_ORDER(s); - s << id; - } - rpcCall(NotifyChangeBreakpointFailed, p); -} - -void IPCEngineGuest::notifyBreakpointAdjusted(BreakpointModelId id, - const BreakpointParameters &bp) -{ - QByteArray p; - { - QDataStream s(&p, QIODevice::WriteOnly); - SET_NATIVE_BYTE_ORDER(s); - s << id << bp; - } - rpcCall(NotifyBreakpointAdjusted, p); -} - -void IPCEngineGuest::updateWatchData(bool fullCycle, const QList &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); -} - -void IPCEngineGuest::frameSourceFetched(qint64 id, const QString &name, const QString &source) -{ - QByteArray p; - { - QDataStream s(&p, QIODevice::WriteOnly); - SET_NATIVE_BYTE_ORDER(s); - s << id; - s << name; - s << source; - } - rpcCall(FrameSourceFetched, p); -} - -} // namespace Internal -} // namespace Debugger - - diff --git a/src/plugins/debugger/lldb/ipcengineguest.h b/src/plugins/debugger/lldb/ipcengineguest.h deleted file mode 100644 index 671e49028d..0000000000 --- a/src/plugins/debugger/lldb/ipcengineguest.h +++ /dev/null @@ -1,191 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/legal -** -** This file is part of Qt Creator. -** -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and Digia. For licensing terms and -** conditions see http://qt.digia.com/licensing. For further information -** use the contact form at http://qt.digia.com/contact-us. -** -** 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. -** -** In addition, as a special exception, Digia gives you certain additional -** rights. These rights are described in the Digia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -****************************************************************************/ - -#ifndef DEBUGGER_IPCENGINE_H -#define DEBUGGER_IPCENGINE_H - -#include "breakhandler.h" -#include "debuggerengine.h" -#include "disassemblerlines.h" -#include "stackhandler.h" -#include "threadshandler.h" - -#include -#include -#include - -namespace Debugger { -namespace Internal { - -class IPCEngineHost; -class IPCEngineGuest : public QObject -{ - Q_OBJECT - -public: - IPCEngineGuest(); - virtual ~IPCEngineGuest(); - - void setLocalHost(IPCEngineHost *); - void setHostDevice(QIODevice *); - - virtual void nuke() = 0; - 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 ContextData &data) = 0; - virtual void executeRunToFunction(const QString &functionName) = 0; - virtual void executeJumpToLine(const ContextData &data) = 0; - virtual void activateFrame(qint64 token) = 0; - virtual void selectThread(qint64 token) = 0; - virtual void disassemble(quint64 pc) = 0; - virtual void addBreakpoint(BreakpointModelId id, const BreakpointParameters &bp) = 0; - virtual void removeBreakpoint(BreakpointModelId id) = 0; - virtual void changeBreakpoint(BreakpointModelId id, const BreakpointParameters &bp) = 0; - virtual void requestUpdateWatchData(const WatchData &data, - const WatchUpdateFlags & flags = WatchUpdateFlags()) = 0; - virtual void fetchFrameSource(qint64 frame) = 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, - FrameSourceFetched = 48 - }; - 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 = quint64(-1)); - void showStatusMessage(const QString &msg, quint64 timeout = quint64(-1)); - - void currentFrameChanged(qint64 token); - void currentThreadChanged(qint64 token); - void listFrames(const StackFrames &); - void listThreads(const Threads &); - void disassembled(quint64 pc, const DisassemblerLines &da); - - void notifyAddBreakpointOk(BreakpointModelId id); - void notifyAddBreakpointFailed(BreakpointModelId id); - void notifyRemoveBreakpointOk(BreakpointModelId id); - void notifyRemoveBreakpointFailed(BreakpointModelId id); - void notifyChangeBreakpointOk(BreakpointModelId id); - void notifyChangeBreakpointFailed(BreakpointModelId id); - void notifyBreakpointAdjusted(BreakpointModelId id, const BreakpointParameters &bp); - - void updateWatchData(bool fullCycle, const QList &); - - void frameSourceFetched(qint64 frame, const QString &name, const QString &sourceCode); - - 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 deleted file mode 100644 index 0562939916..0000000000 --- a/src/plugins/debugger/lldb/ipcenginehost.cpp +++ /dev/null @@ -1,661 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/legal -** -** This file is part of Qt Creator. -** -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and Digia. For licensing terms and -** conditions see http://qt.digia.com/licensing. For further information -** use the contact form at http://qt.digia.com/contact-us. -** -** 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. -** -** In addition, as a special exception, Digia gives you certain additional -** rights. These rights are described in the Digia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -****************************************************************************/ - -#include "ipcenginehost.h" - -#include "ipcengineguest.h" -#include "debuggerstartparameters.h" -#include "breakhandler.h" -#include "breakpoint.h" -#include "disassemblerlines.h" -#include "moduleshandler.h" -#include "registerhandler.h" -#include "stackhandler.h" -#include "watchhandler.h" -#include "watchutils.h" -#include "threadshandler.h" -#include "disassembleragent.h" -#include "memoryagent.h" -#include "debuggerstreamops.h" -#include "debuggercore.h" - -#include - -#include -#include -#include -#include -#include - -#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_localGuest(0) - , m_nextMessagePayloadSize(0) - , m_cookie(1) - , m_device(0) -{ - connect(this, SIGNAL(stateChanged(Debugger::DebuggerState)), SLOT(m_stateChanged(Debugger::DebuggerState))); -} - -IPCEngineHost::~IPCEngineHost() -{ - delete m_device; -} - -void IPCEngineHost::setLocalGuest(IPCEngineGuest *guest) -{ - m_localGuest = guest; -} - -void IPCEngineHost::setGuestDevice(QIODevice *device) -{ - if (m_device) { - disconnect(m_device, SIGNAL(readyRead()), this, SLOT(readyRead())); - delete m_device; - } - m_device = device; - 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.toStringList(); - } - 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 ContextData &data) -{ - QByteArray p; - { - QDataStream s(&p, QIODevice::WriteOnly); - SET_NATIVE_BYTE_ORDER(s); - s << data.fileName; - s << quint64(data.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 ContextData &data) -{ - QByteArray p; - { - QDataStream s(&p, QIODevice::WriteOnly); - SET_NATIVE_BYTE_ORDER(s); - s << data.fileName; - s << quint64(data.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(ThreadId id) -{ - resetLocation(); - QTC_ASSERT(id.isValid(), return); - QByteArray p; - { - QDataStream s(&p, QIODevice::WriteOnly); - SET_NATIVE_BYTE_ORDER(s); - s << id.raw(); - } - rpcCall(SelectThread, p); -} - -void IPCEngineHost::fetchDisassembler(DisassemblerAgent *v) -{ - quint64 address = v->location().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::insertBreakpoint(BreakpointModelId id) -{ - breakHandler()->notifyBreakpointInsertProceeding(id); - QByteArray p; - { - QDataStream s(&p, QIODevice::WriteOnly); - SET_NATIVE_BYTE_ORDER(s); - s << id; - s << breakHandler()->breakpointData(id); - } - rpcCall(AddBreakpoint, p); -} - -void IPCEngineHost::removeBreakpoint(BreakpointModelId id) -{ - breakHandler()->notifyBreakpointRemoveProceeding(id); - QByteArray p; - { - QDataStream s(&p, QIODevice::WriteOnly); - SET_NATIVE_BYTE_ORDER(s); - s << id; - } - rpcCall(RemoveBreakpoint, p); -} - -void IPCEngineHost::changeBreakpoint(BreakpointModelId id) -{ - breakHandler()->notifyBreakpointChangeProceeding(id); - QByteArray p; - { - QDataStream s(&p, QIODevice::WriteOnly); - SET_NATIVE_BYTE_ORDER(s); - s << id; - s << breakHandler()->breakpointData(id); - } - rpcCall(RemoveBreakpoint, p); -} - -void IPCEngineHost::updateWatchData(const WatchData &data, - const WatchUpdateFlags &flags) -{ - Q_UNUSED(flags); - QByteArray p; - { - QDataStream s(&p, QIODevice::WriteOnly); - SET_NATIVE_BYTE_ORDER(s); - s << data; - } - rpcCall(RequestUpdateWatchData, p); -} - -void IPCEngineHost::fetchFrameSource(qint64 id) -{ - QByteArray p; - { - QDataStream s(&p, QIODevice::WriteOnly); - SET_NATIVE_BYTE_ORDER(s); - s << id; - } - rpcCall(FetchFrameSource, p); -} - -void IPCEngineHost::rpcCallback(quint64 f, QByteArray payload) -{ - switch (f) { - default: { - showMessage(QLatin1String("IPC Error: unhandled id in guest to host call")); - const QString logMessage = tr("Fatal engine shutdown. Incompatible binary or IPC error."); - showMessage(logMessage, LogError); - showStatusMessage(logMessage); - } - nuke(); - 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); - if (!sh->currentFrame().isUsable() || QFileInfo(sh->currentFrame().file).exists()) - gotoLocation(Location(sh->currentFrame(), true)); - else if (!m_sourceAgents.contains(sh->currentFrame().file)) - fetchFrameSource(token); - foreach (SourceAgent *agent, m_sourceAgents.values()) - agent->updateLocationMarker(); - } - break; - case IPCEngineGuest::CurrentThreadChanged: - { - QDataStream s(payload); - SET_NATIVE_BYTE_ORDER(s); - quint64 token; - s >> token; - threadsHandler()->setCurrentThread(ThreadId(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; - DisassemblerLines lines; - s >> pc; - s >> lines; - DisassemblerAgent *view = m_frameToDisassemblerAgent.take(pc); - if (view) - view->setContents(lines); - } - break; - case IPCEngineGuest::UpdateWatchData: - { - QDataStream s(payload); - SET_NATIVE_BYTE_ORDER(s); - bool fullCycle; - qint64 count; - QList 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->insertData(wd); - } - break; - case IPCEngineGuest::NotifyAddBreakpointOk: - { - attemptBreakpointSynchronization(); - QDataStream s(payload); - SET_NATIVE_BYTE_ORDER(s); - quint64 d; - s >> d; - BreakpointModelId id = BreakpointModelId::fromInternalId(d); - breakHandler()->notifyBreakpointInsertOk(id); - } - break; - case IPCEngineGuest::NotifyAddBreakpointFailed: - { - QDataStream s(payload); - SET_NATIVE_BYTE_ORDER(s); - quint64 d; - s >> d; - BreakpointModelId id = BreakpointModelId::fromInternalId(d); - breakHandler()->notifyBreakpointInsertFailed(id); - } - break; - case IPCEngineGuest::NotifyRemoveBreakpointOk: - { - QDataStream s(payload); - SET_NATIVE_BYTE_ORDER(s); - quint64 d; - s >> d; - BreakpointModelId id = BreakpointModelId::fromInternalId(d); - breakHandler()->notifyBreakpointRemoveOk(id); - } - break; - case IPCEngineGuest::NotifyRemoveBreakpointFailed: - { - QDataStream s(payload); - SET_NATIVE_BYTE_ORDER(s); - quint64 d; - s >> d; - BreakpointModelId id = BreakpointModelId::fromInternalId(d); - breakHandler()->notifyBreakpointRemoveFailed(id); - } - break; - case IPCEngineGuest::NotifyChangeBreakpointOk: - { - QDataStream s(payload); - SET_NATIVE_BYTE_ORDER(s); - quint64 d; - s >> d; - BreakpointModelId id = BreakpointModelId::fromInternalId(d); - breakHandler()->notifyBreakpointChangeOk(id); - } - break; - case IPCEngineGuest::NotifyChangeBreakpointFailed: - { - QDataStream s(payload); - SET_NATIVE_BYTE_ORDER(s); - quint64 d; - s >> d; - BreakpointModelId id = BreakpointModelId::fromInternalId(d); - breakHandler()->notifyBreakpointChangeFailed(id); - } - break; - case IPCEngineGuest::NotifyBreakpointAdjusted: - { - QDataStream s(payload); - SET_NATIVE_BYTE_ORDER(s); - quint64 dd; - BreakpointParameters d; - s >> dd >> d; - BreakpointModelId id = BreakpointModelId::fromInternalId(dd); - breakHandler()->notifyBreakpointAdjusted(id, d); - } - break; - case IPCEngineGuest::FrameSourceFetched: - { - QDataStream s(payload); - SET_NATIVE_BYTE_ORDER(s); - qint64 token; - QString path; - QString source; - s >> token >> path >> source; - SourceAgent *agent = new SourceAgent(this); - agent->setSourceProducerName(startParameters().connParams.host); - agent->setContent(path, source); - m_sourceAgents.insert(path, agent); - agent->updateLocationMarker(); - } - break; - } -} - -void IPCEngineHost::m_stateChanged(Debugger::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_localGuest) { - QMetaObject::invokeMethod(m_localGuest, - "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'); - QLocalSocket *sock = qobject_cast(m_device); - if (sock) - sock->flush(); - } -} - -void IPCEngineHost::readyRead() -{ - QDataStream s(m_device); - SET_NATIVE_BYTE_ORDER(s); - if (!m_nextMessagePayloadSize) { - if (quint64(m_device->bytesAvailable ()) < 3 * sizeof(quint64)) - 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")); - nuke(); - return; - } - rpcCallback(m_nextMessageFunction, payload); - m_nextMessagePayloadSize = 0; - if (quint64(m_device->bytesAvailable()) >= 3 * sizeof(quint64)) - 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 deleted file mode 100644 index 8364d50657..0000000000 --- a/src/plugins/debugger/lldb/ipcenginehost.h +++ /dev/null @@ -1,140 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/legal -** -** This file is part of Qt Creator. -** -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and Digia. For licensing terms and -** conditions see http://qt.digia.com/licensing. For further information -** use the contact form at http://qt.digia.com/contact-us. -** -** 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. -** -** In addition, as a special exception, Digia gives you certain additional -** rights. These rights are described in the Digia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -****************************************************************************/ - -#ifndef DEBUGGER_IPCENGINE_HOST_H -#define DEBUGGER_IPCENGINE_HOST_H - -#include "debuggerengine.h" -#include "threadshandler.h" -#include "stackhandler.h" -#include "breakhandler.h" -#include "sourceagent.h" - -#include -#include -#include - -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, - FetchFrameSource = 26 - }; - 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 ContextData &data); - void executeRunToFunction(const QString &functionName); - void executeJumpToLine(const ContextData &data); - void activateFrame(int index); - void selectThread(ThreadId index); - void fetchDisassembler(DisassemblerAgent *); - bool acceptsBreakpoint(BreakpointModelId) const { return true; } // FIXME - void insertBreakpoint(BreakpointModelId id); - void removeBreakpoint(BreakpointModelId id); - void changeBreakpoint(BreakpointModelId id); - void updateWatchData(const WatchData &data, - const WatchUpdateFlags &flags = WatchUpdateFlags()); - void fetchFrameSource(qint64 id); - bool hasCapability(unsigned) const { return false; } - - void rpcCall(Function f, QByteArray payload = QByteArray()); -protected: - virtual void nuke() = 0; -public slots: - void rpcCallback(quint64 f, QByteArray payload = QByteArray()); -private slots: - void m_stateChanged(Debugger::DebuggerState state); - void readyRead(); -private: - IPCEngineGuest *m_localGuest; - quint64 m_nextMessageCookie; - quint64 m_nextMessageFunction; - quint64 m_nextMessagePayloadSize; - quint64 m_cookie; - QIODevice *m_device; - QHash m_frameToDisassemblerAgent; - QHash m_sourceAgents; -}; - -} // namespace Internal -} // namespace Debugger - -#endif // DEBUGGER_LLDBENGINE_H diff --git a/src/plugins/debugger/lldb/lldbenginehost.cpp b/src/plugins/debugger/lldb/lldbenginehost.cpp deleted file mode 100644 index 2bac195eb2..0000000000 --- a/src/plugins/debugger/lldb/lldbenginehost.cpp +++ /dev/null @@ -1,232 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/legal -** -** This file is part of Qt Creator. -** -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and Digia. For licensing terms and -** conditions see http://qt.digia.com/licensing. For further information -** use the contact form at http://qt.digia.com/contact-us. -** -** 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. -** -** In addition, as a special exception, Digia gives you certain additional -** rights. These rights are described in the Digia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -****************************************************************************/ - -#include "lldbenginehost.h" - -#include "debuggerstartparameters.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 "disassembleragent.h" -#include "memoryagent.h" - -#include -#include - -#include -#include -#include -#include -#include - -namespace Debugger { -namespace Internal { - -SshIODevice::SshIODevice(QSsh::SshRemoteProcessRunner *r) - : runner(r) - , buckethead(0) -{ - setOpenMode(QIODevice::ReadWrite | QIODevice::Unbuffered); - connect (runner, SIGNAL(processStarted()), this, SLOT(processStarted())); - connect(runner, SIGNAL(readyReadStandardOutput()), this, SLOT(outputAvailable())); - connect(runner, SIGNAL(readyReadStandardError()), this, SLOT(errorOutputAvailable())); -} - -SshIODevice::~SshIODevice() -{ - delete runner; -} - -qint64 SshIODevice::bytesAvailable () const -{ - qint64 r = QIODevice::bytesAvailable(); - foreach (const QByteArray &bucket, buckets) - r += bucket.size(); - r-= buckethead; - return r; -} -qint64 SshIODevice::writeData (const char * data, qint64 maxSize) -{ - if (proc == 0) { - startupbuffer += QByteArray::fromRawData(data, maxSize); - return maxSize; - } - proc->write(data, maxSize); - return maxSize; -} -qint64 SshIODevice::readData (char * data, qint64 maxSize) -{ - if (proc == 0) - return 0; - qint64 size = maxSize; - while (size > 0) { - if (!buckets.size()) - return maxSize - size; - QByteArray &bucket = buckets.head(); - if ((size + buckethead) >= bucket.size()) { - int d = bucket.size() - buckethead; - memcpy(data, bucket.data() + buckethead, d); - data += d; - size -= d; - buckets.dequeue(); - buckethead = 0; - } else { - memcpy(data, bucket.data() + buckethead, size); - data += size; - buckethead += size; - size = 0; - } - } - return maxSize - size; -} - -void SshIODevice::processStarted() -{ - runner->writeDataToProcess(startupbuffer); -} - -void SshIODevice::outputAvailable() -{ - buckets.enqueue(runner->readAllStandardOutput()); - emit readyRead(); -} - -void SshIODevice::errorOutputAvailable() -{ - fprintf(stderr, "%s", runner->readAllStandardError().data()); -} - - -LldbEngineHost::LldbEngineHost(const DebuggerStartParameters &startParameters) - :IPCEngineHost(startParameters), m_ssh(0) -{ - showMessage(QLatin1String("setting up coms")); - setObjectName(QLatin1String("LLDBEngine")); - - if (startParameters.startMode == StartRemoteEngine) - { - m_guestProcess = 0; - QSsh::SshRemoteProcessRunner * const runner = new QSsh::SshRemoteProcessRunner; - connect (runner, SIGNAL(connectionError(QSsh::SshError)), - this, SLOT(sshConnectionError(QSsh::SshError))); - runner->run(startParameters.serverStartScript.toUtf8(), startParameters.connParams); - setGuestDevice(new SshIODevice(runner)); - } else { - m_guestProcess = new QProcess(this); - - connect(m_guestProcess, SIGNAL(finished(int,QProcess::ExitStatus)), - this, SLOT(finished(int,QProcess::ExitStatus))); - - connect(m_guestProcess, SIGNAL(readyReadStandardError()), this, - SLOT(stderrReady())); - - - QString a = Core::ICore::resourcePath() + QLatin1String("/qtcreator-lldb"); - if (getenv("QTC_LLDB_GUEST") != 0) - a = QString::fromLocal8Bit(getenv("QTC_LLDB_GUEST")); - - showStatusMessage(QString(QLatin1String("starting %1")).arg(a)); - - m_guestProcess->start(a, QStringList(), QIODevice::ReadWrite | QIODevice::Unbuffered); - m_guestProcess->setReadChannel(QProcess::StandardOutput); - - if (!m_guestProcess->waitForStarted()) { - showStatusMessage(tr("qtcreator-lldb failed to start: %1").arg(m_guestProcess->errorString())); - notifyEngineSpontaneousShutdown(); - return; - } - - setGuestDevice(m_guestProcess); - } -} - -LldbEngineHost::~LldbEngineHost() -{ - showMessage(QLatin1String("tear down qtcreator-lldb")); - - if (m_guestProcess) { - disconnect(m_guestProcess, SIGNAL(finished(int,QProcess::ExitStatus)), - this, SLOT(finished(int,QProcess::ExitStatus))); - - - m_guestProcess->terminate(); - m_guestProcess->kill(); - } - if (m_ssh && m_ssh->isProcessRunning()) { - // TODO: openssh doesn't do that - - m_ssh->sendSignalToProcess(QSsh::SshRemoteProcess::KillSignal); - } -} - -void LldbEngineHost::nuke() -{ - stderrReady(); - showMessage(QLatin1String("Nuke engaged. Bug in Engine/IPC or incompatible IPC versions. "), LogError); - showStatusMessage(tr("Fatal engine shutdown. Consult debugger log for details.")); - m_guestProcess->terminate(); - m_guestProcess->kill(); - notifyEngineSpontaneousShutdown(); -} -void LldbEngineHost::sshConnectionError(QSsh::SshError e) -{ - showStatusMessage(tr("SSH connection error: %1").arg(e)); -} - -void LldbEngineHost::finished(int, QProcess::ExitStatus status) -{ - showMessage(QString(QLatin1String("guest went bye bye. exit status: %1 and code: %2")) - .arg(status).arg(m_guestProcess->exitCode()), LogError); - nuke(); -} - -void LldbEngineHost::stderrReady() -{ - fprintf(stderr,"%s", m_guestProcess->readAllStandardError().data()); -} - -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 deleted file mode 100644 index 52df2b373e..0000000000 --- a/src/plugins/debugger/lldb/lldbenginehost.h +++ /dev/null @@ -1,88 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/legal -** -** This file is part of Qt Creator. -** -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and Digia. For licensing terms and -** conditions see http://qt.digia.com/licensing. For further information -** use the contact form at http://qt.digia.com/contact-us. -** -** 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. -** -** In addition, as a special exception, Digia gives you certain additional -** rights. These rights are described in the Digia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -****************************************************************************/ - -#ifndef DEBUGGER_LLDBENGINE_HOST_H -#define DEBUGGER_LLDBENGINE_HOST_H - -#include "ipcenginehost.h" -#include -#include -#include -#include - -#include -#include - -namespace Debugger { -namespace Internal { - -class SshIODevice : public QIODevice -{ -Q_OBJECT -public: - SshIODevice(QSsh::SshRemoteProcessRunner *r); - ~SshIODevice(); - virtual qint64 bytesAvailable () const; - virtual qint64 writeData (const char * data, qint64 maxSize); - virtual qint64 readData (char * data, qint64 maxSize); -private slots: - void processStarted(); - void outputAvailable(); - void errorOutputAvailable(); -private: - QSsh::SshRemoteProcessRunner *runner; - QSsh::SshRemoteProcess::Ptr proc; - int buckethead; - QQueue buckets; - QByteArray startupbuffer; -}; - -class LldbEngineHost : public IPCEngineHost -{ - Q_OBJECT - -public: - explicit LldbEngineHost(const DebuggerStartParameters &startParameters); - ~LldbEngineHost(); - -private: - QProcess *m_guestProcess; - QSsh::SshRemoteProcessRunner *m_ssh; -protected: - void nuke(); -private slots: - void sshConnectionError(QSsh::SshError); - void finished(int, QProcess::ExitStatus); - void stderrReady(); -}; - -} // namespace Internal -} // namespace Debugger - -#endif // DEBUGGER_LLDBENGINE_HOST_H diff --git a/src/plugins/debugger/lldb/lldbhost.pri b/src/plugins/debugger/lldb/lldbhost.pri deleted file mode 100644 index 0e9297d7e3..0000000000 --- a/src/plugins/debugger/lldb/lldbhost.pri +++ /dev/null @@ -1,20 +0,0 @@ -WITH_LLDB = $$(WITH_LLDB) - -HEADERS += $$PWD/ipcenginehost.h \ - $$PWD/lldbenginehost.h - -SOURCES += $$PWD/ipcenginehost.cpp \ - $$PWD/lldbenginehost.cpp - -INCLUDEPATH+= - -FORMS += - -RESOURCES += - -!isEmpty(WITH_LLDB) { - DEFINES += WITH_LLDB - HEADERS += $$PWD/lldboptionspage.h - SOURCES += $$PWD/lldboptionspage.cpp - FORMS += $$PWD/lldboptionspagewidget.ui -} diff --git a/src/plugins/debugger/lldb/lldboptionspage.cpp b/src/plugins/debugger/lldb/lldboptionspage.cpp deleted file mode 100644 index 9fe0cb2a30..0000000000 --- a/src/plugins/debugger/lldb/lldboptionspage.cpp +++ /dev/null @@ -1,109 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/legal -** -** This file is part of Qt Creator. -** -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and Digia. For licensing terms and -** conditions see http://qt.digia.com/licensing. For further information -** use the contact form at http://qt.digia.com/contact-us. -** -** 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. -** -** In addition, as a special exception, Digia gives you certain additional -** rights. These rights are described in the Digia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -****************************************************************************/ - -#include "lldboptionspage.h" -#include "debuggerconstants.h" -#include "debuggerinternalconstants.h" - -#include - -#include -#include -#include -#include -#include - -namespace Debugger { -namespace Internal { - -LldbOptionsPageWidget::LldbOptionsPageWidget(QWidget *parent, QSettings *s_) - : QWidget(parent) - , s(s_) -{ - m_ui.setupUi(this); - load(); -} - -void LldbOptionsPageWidget::save() -{ - s->beginGroup(QLatin1String("LLDB")); - s->setValue(QLatin1String("enabled"), m_ui.enableLldb->isChecked ()); - s->setValue(QLatin1String("gdbEmu"), m_ui.gdbEmu->isChecked ()); - s->endGroup(); -} - -void LldbOptionsPageWidget::load() -{ - s->beginGroup(QLatin1String("LLDB")); - m_ui.enableLldb->setChecked(s->value(QLatin1String("enabled"), false).toBool()); - m_ui.gdbEmu->setChecked(s->value(QLatin1String("gdbEmu"), true).toBool()); - s->endGroup(); -} - -// ---------- LldbOptionsPage -LldbOptionsPage::LldbOptionsPage() -{ - // m_options->fromSettings(Core::ICore::settings()); - setId(QLatin1String("F.Lldb")); - setDisplayName(tr("LLDB")); - setCategory(Debugger::Constants::DEBUGGER_SETTINGS_CATEGORY); - setDisplayCategory(QCoreApplication::translate("Debugger", Constants::DEBUGGER_SETTINGS_TR_CATEGORY)); - setCategoryIcon(QIcon(QLatin1String(Constants::DEBUGGER_COMMON_SETTINGS_CATEGORY_ICON))); -} - -QWidget *LldbOptionsPage::createPage(QWidget *parent) -{ - m_widget = new LldbOptionsPageWidget(parent, Core::ICore::settings()); - return m_widget; -} - -void LldbOptionsPage::apply() -{ - if (!m_widget) - return; - m_widget->save(); -} - -void LldbOptionsPage::finish() -{ -} - -bool LldbOptionsPage::matches(const QString &s) const -{ - return QString(s.toLower()).contains("lldb"); -} - -void addLldbOptionPages(QList *opts) -{ - opts->push_back(new LldbOptionsPage); -} - - -} // namespace Internal -} // namespace Debugger diff --git a/src/plugins/debugger/lldb/lldboptionspage.h b/src/plugins/debugger/lldb/lldboptionspage.h deleted file mode 100644 index 78cd3c7e67..0000000000 --- a/src/plugins/debugger/lldb/lldboptionspage.h +++ /dev/null @@ -1,80 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/legal -** -** This file is part of Qt Creator. -** -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and Digia. For licensing terms and -** conditions see http://qt.digia.com/licensing. For further information -** use the contact form at http://qt.digia.com/contact-us. -** -** 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. -** -** In addition, as a special exception, Digia gives you certain additional -** rights. These rights are described in the Digia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -****************************************************************************/ - -#ifndef LLDBSETTINGSPAGE_H -#define LLDBSETTINGSPAGE_H - -#include -#include "ui_lldboptionspagewidget.h" - -#include -#include -#include -#include - -namespace Debugger { -namespace Internal { - -class LldbOptionsPageWidget : public QWidget -{ - Q_OBJECT - -public: - explicit LldbOptionsPageWidget(QWidget *parent, QSettings *s); - -public slots: - void save(); - void load(); - -private: - Ui::LldbOptionsPageWidget m_ui; - QSettings *s; -}; - -class LldbOptionsPage : public Core::IOptionsPage -{ - Q_OBJECT - -public: - LldbOptionsPage(); - - // IOptionsPage - QWidget *createPage(QWidget *parent); - void apply(); - void finish(); - bool matches(const QString &) const; - -private: - QPointer m_widget; -}; - -} // namespace Internal -} // namespace Debugger - -#endif // LLDBSETTINGSPAGE_H diff --git a/src/plugins/debugger/lldb/lldboptionspagewidget.ui b/src/plugins/debugger/lldb/lldboptionspagewidget.ui deleted file mode 100644 index 78e77699f0..0000000000 --- a/src/plugins/debugger/lldb/lldboptionspagewidget.ui +++ /dev/null @@ -1,59 +0,0 @@ - - - Debugger::Internal::LldbOptionsPageWidget - - - - 0 - 0 - 522 - 512 - - - - - - - - - - Enable LLDB - - - true - - - false - - - - - - Use GDB Python dumpers - - - false - - - - - - - - - - Qt::Vertical - - - - 20 - 203 - - - - - - - - - diff --git a/src/plugins/debugger/lldblib/guest/README b/src/plugins/debugger/lldblib/guest/README new file mode 100644 index 0000000000..be9d4fbee7 --- /dev/null +++ b/src/plugins/debugger/lldblib/guest/README @@ -0,0 +1,31 @@ +LLDB Guest Engine + +You can use the LLDB debugger from the LLVM project with the Qt Creator debugger +plugin on Mac OS. + +For the Qt Creator build to pick up the LLDB Guest Engine, +you must download the LLDB debugger and configure it +to be included in the Qt Creator build. + +To debug an application, Qt Creator must access the memory of the application. +On Mac OS X, this requires code signing. + +To enable LLDB debugger support in Qt Creator: + +1. To download the LLDB debugger, enter the following command: + svn co http://llvm.org/svn/llvm-project/lldb/trunk lldb + +2. To sign the code, follow the instructions in lldb/docs/code-signing.txt. + +3. To open LLDB in Xcode for building, enter the following command: + open lldb.xcodeproj + then select the Release target and press the build button. + +4. In Xcode, press the build button. + +5. type the following to have the qt creator build system find your lldb build: + export WITH_LLDB=/path/to/lldb + +6. To rebuild Qt Creator, change back to the top level directory of + the Qt Creator source, and enter the following command: + qmake -r && make diff --git a/src/plugins/debugger/lldblib/guest/lldbengineguest.cpp b/src/plugins/debugger/lldblib/guest/lldbengineguest.cpp new file mode 100644 index 0000000000..312a6cb457 --- /dev/null +++ b/src/plugins/debugger/lldblib/guest/lldbengineguest.cpp @@ -0,0 +1,761 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** 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. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +****************************************************************************/ + +#define QT_NO_CAST_FROM_ASCII + +#include "lldbengineguest.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 +#include +#include +#include +#include +#include + +#include + +#define DEBUG_FUNC_ENTER \ + showMessage(QString(QLatin1String("LLDB guest engine: %1 ")) \ + .arg(QLatin1String(Q_FUNC_INFO))); \ + qDebug("%s", Q_FUNC_INFO) + +#define SYNC_INFERIOR_OR(x) if (m_running) { x; } + + +namespace Debugger { +namespace Internal { + +void LldbEventListener::listen(lldb::SBListener *listener) +{ + while (true) { + lldb::SBEvent event; + if (listener->WaitForEvent(1000, event)) + emit lldbEvent(&event); + } +} + +LldbEngineGuest::LldbEngineGuest() + : IPCEngineGuest() + , m_running (false) + , m_worker (new LldbEventListener) + , m_lldb (new lldb::SBDebugger) + , m_target (new lldb::SBTarget) + , m_process (new lldb::SBProcess) + , m_listener(new lldb::SBListener("bla")) + , m_relistFrames (false) +#if defined(HAVE_LLDB_PRIVATE) + , py (new PythonLLDBToGdbMiHack) +#endif +{ + qRegisterMetaType("lldb::SBListener *"); + qRegisterMetaType("lldb::SBEvent *"); + + m_worker->moveToThread(&m_wThread); + connect(m_worker, SIGNAL(lldbEvent(lldb::SBEvent*)), this, + SLOT(lldbEvent(lldb::SBEvent*)), Qt::BlockingQueuedConnection); + m_wThread.start(); + setObjectName(QLatin1String("LLDBEngineGuest")); +} + +LldbEngineGuest::~LldbEngineGuest() +{ + delete m_lldb; + delete m_target; + delete m_process; + delete m_listener; +} + + +void LldbEngineGuest::nuke() +{ + ::exit(4); +} + +void LldbEngineGuest::setupEngine() +{ + DEBUG_FUNC_ENTER; + + lldb::SBDebugger::Initialize(); + + *m_lldb = lldb::SBDebugger::Create(); + m_lldb->Initialize(); + if (m_lldb->IsValid()) + notifyEngineSetupOk(); + else + notifyEngineSetupFailed(); + +} + +void LldbEngineGuest::setupInferior(const QString &executable, + const QStringList &args, const QStringList &env) +{ + DEBUG_FUNC_ENTER; + + foreach (const QString &s, args) { + m_arguments.append(s.toLocal8Bit()); + } + foreach (const QString &s, env) { + m_environment.append(s.toLocal8Bit()); + } + + qDebug("creating target for %s", executable.toLocal8Bit().data()); + showStatusMessage(QLatin1String("starting ") + executable); + *m_target = m_lldb->CreateTarget(executable.toLocal8Bit().data()); + if (!m_target->IsValid()) { + notifyInferiorSetupFailed(); + return; + } + DEBUG_FUNC_ENTER; + + const char **argp = new const char *[m_arguments.count() + 1]; + argp[m_arguments.count()] = 0; + for (int i = 0; i < m_arguments.count(); i++) { + argp[i] = m_arguments[i].data(); + } + + const char **envp = new const char *[m_environment.count() + 1]; + envp[m_environment.count()] = 0; + for (int i = 0; i < m_environment.count(); i++) { + envp[i] = m_environment[i].data(); + } + lldb::SBError err; + *m_process = m_target->Launch(argp, envp, NULL, NULL, true, err); + + if (!err.Success()) { + showMessage(QString::fromLocal8Bit(err.GetCString())); + qDebug() << err.GetCString(); + notifyInferiorSetupFailed(); + } + + /* + * note, the actual string ptrs are still valid. They are in m_environment. + * They probably leak. Considered the marvelous API, there is not much we can do + */ + delete [] envp; + + if (!m_process->IsValid()) + notifyEngineRunFailed(); + QTC_ASSERT(m_listener->IsValid(), qDebug() << false); + m_listener->StartListeningForEvents(m_process->GetBroadcaster(), UINT32_MAX); + QMetaObject::invokeMethod(m_worker, "listen", Qt::QueuedConnection, + Q_ARG(lldb::SBListener *, m_listener)); + notifyInferiorSetupOk(); +} + +void LldbEngineGuest::runEngine() +{ + DEBUG_FUNC_ENTER; + m_process->Continue(); +} + +void LldbEngineGuest::shutdownInferior() +{ + DEBUG_FUNC_ENTER; + m_process->Kill(); +} + +void LldbEngineGuest::shutdownEngine() +{ + DEBUG_FUNC_ENTER; + m_currentFrame = lldb::SBFrame(); + m_currentThread = lldb::SBThread(); + m_breakpoints.clear(); + m_localesCache.clear(); + + /* + * this leaks. However, Terminate is broken and lldb leaks anyway + * We should kill the engine guest process + */ + + *m_lldb = lldb::SBDebugger(); + // leakd.Terminate(); + notifyEngineShutdownOk(); +} + +void LldbEngineGuest::detachDebugger() +{ + DEBUG_FUNC_ENTER; +} + +void LldbEngineGuest::executeStep() +{ + DEBUG_FUNC_ENTER; + + if (!m_currentThread.IsValid()) + return; + m_currentThread.StepInto(); +} + +void LldbEngineGuest::executeStepOut() +{ + DEBUG_FUNC_ENTER; + + if (!m_currentThread.IsValid()) + return; + m_currentThread.StepOut(); +} + +void LldbEngineGuest::executeNext() +{ + DEBUG_FUNC_ENTER; + + if (!m_currentThread.IsValid()) + return; + m_currentThread.StepOver(); +} + +void LldbEngineGuest::executeStepI() +{ + DEBUG_FUNC_ENTER; + + if (!m_currentThread.IsValid()) + return; + m_currentThread.StepInstruction(false); +} + +void LldbEngineGuest::executeNextI() +{ + DEBUG_FUNC_ENTER; + + if (!m_currentThread.IsValid()) + return; + m_currentThread.StepInstruction(true); +} + +void LldbEngineGuest::continueInferior() +{ + DEBUG_FUNC_ENTER; + + notifyInferiorRunRequested(); + m_process->Continue(); + showStatusMessage(QLatin1String("resuming inferior")); +} +void LldbEngineGuest::interruptInferior() +{ + DEBUG_FUNC_ENTER; + + m_process->Stop(); + notifyInferiorStopOk(); + m_relistFrames = true; + updateThreads(); +} + +void LldbEngineGuest::executeRunToLine(const ContextData &data); +{ + DEBUG_FUNC_ENTER; + + // TODO + Q_UNUSED(data); +} + +void LldbEngineGuest::executeRunToFunction(const QString &functionName) +{ + DEBUG_FUNC_ENTER; + + // TODO + Q_UNUSED(functionName); +} +void LldbEngineGuest::executeJumpToLine(const ContextData &data); +{ + DEBUG_FUNC_ENTER; + + // TODO + Q_UNUSED(data); +} + +void LldbEngineGuest::activateFrame(qint64 token) +{ + DEBUG_FUNC_ENTER; + SYNC_INFERIOR_OR(showMessage(QLatin1String( + "activateFrame called while inferior running")); return); + + currentFrameChanged(token); + m_localesCache.clear(); + + lldb::SBFrame fr = m_currentThread.GetFrameAtIndex(token); + m_currentFrame = fr; + lldb::SBSymbolContext context = fr.GetSymbolContext(lldb::eSymbolContextEverything); + lldb::SBValueList values = fr.GetVariables(true, true, false, true); + QList wd; + QByteArray iname = "local"; + for (uint i = 0; i < values.GetSize(); i++) { + lldb::SBValue v = values.GetValueAtIndex(i); + if (!v.IsInScope(fr)) + continue; + getWatchDataR(v, 1, iname, wd); + } + updateWatchData(true, wd); +} + +void LldbEngineGuest::requestUpdateWatchData(const Internal::WatchData &data, + const Internal::WatchUpdateFlags &) +{ + DEBUG_FUNC_ENTER; + SYNC_INFERIOR_OR(return); + + lldb::SBValue v = m_localesCache.value(QString::fromUtf8(data.iname)); + QList wd; + for (uint j = 0; j < v.GetNumChildren(); j++) { + lldb::SBValue vv = v.GetChildAtIndex(j); + getWatchDataR(vv, 1, data.iname, wd); + } + updateWatchData(false, wd); +} + +void LldbEngineGuest::getWatchDataR(lldb::SBValue v, int level, + const QByteArray &p_iname, QList &wd) +{ + QByteArray iname = p_iname + '.' + QByteArray(v.GetName()); + m_localesCache.insert(QString::fromLocal8Bit(iname), v); + +#if defined(HAVE_LLDB_PRIVATE) + wd += py->expand(p_iname, v, m_currentFrame, *m_process); +#else + WatchData d; + d.name = QString::fromLocal8Bit(v.GetName()); + d.iname = iname; + d.type = QByteArray(v.GetTypeName()).trimmed(); + d.value = (QString::fromLocal8Bit(v.GetValue(m_currentFrame))); + d.hasChildren = v.GetNumChildren(); + d.state = WatchData::State(0); + wd.append(d); +#endif + + if (--level > 0) { + for (uint j = 0; j < v.GetNumChildren(); j++) { + lldb::SBValue vv = v.GetChildAtIndex(j); + getWatchDataR(vv, level, iname, wd); + } + } +} + +void LldbEngineGuest::disassemble(quint64 pc) +{ + DEBUG_FUNC_ENTER; + SYNC_INFERIOR_OR(return); + + if (!m_currentThread.IsValid()) + return; + for (uint j = 0; j < m_currentThread.GetNumFrames(); j++) { + lldb::SBFrame fr = m_currentThread.GetFrameAtIndex(j); + if (pc == fr.GetPCAddress().GetLoadAddress(*m_target)) { + QString linesStr = QString::fromLocal8Bit(fr.Disassemble()); + DisassemblerLines lines; + foreach (const QString &lineStr, linesStr.split(QLatin1Char('\n'))) { + lines.appendLine(DisassemblerLine(lineStr)); + } + disassembled(pc, lines); + } + } +} +void LldbEngineGuest::fetchFrameSource(qint64 frame) +{ + QFile f(m_frame_to_file.value(frame)); + f.open(QFile::ReadOnly); + frameSourceFetched(frame, QFileInfo(m_frame_to_file.value(frame)).fileName() + , QString::fromLocal8Bit(f.readAll())); +} + +void LldbEngineGuest::addBreakpoint(BreakpointId id, + const Internal::BreakpointParameters &bp_) +{ + DEBUG_FUNC_ENTER; + SYNC_INFERIOR_OR(notifyAddBreakpointFailed(id); return); + + Internal::BreakpointParameters bp(bp_); + + lldb::SBBreakpoint llbp = m_target->BreakpointCreateByLocation( + bp.fileName.toLocal8Bit().constData(), bp.lineNumber); + if (llbp.IsValid()) { + m_breakpoints.insert(id, llbp); + + llbp.SetIgnoreCount(bp.ignoreCount); + bp.ignoreCount = llbp.GetIgnoreCount(); + bp.enabled = llbp.IsEnabled(); + + lldb::SBBreakpointLocation location = llbp.GetLocationAtIndex(0); + if (location.IsValid()) { + bp.address = location.GetLoadAddress(); + + // FIXME get those from lldb + bp.lineNumber = bp.lineNumber; + bp.fileName = bp.fileName; + notifyAddBreakpointOk(id); + showMessage(QLatin1String("[BB] ok.")); + notifyBreakpointAdjusted(id, bp); + } else { + m_breakpoints.take(id); + showMessage(QLatin1String("[BB] failed. cant resolve yet")); +// notifyAddBreakpointFailed(id); +// notifyAddBreakpointOk(id); + } + } else { + showMessage(QLatin1String("[BB] failed. dunno.")); + notifyAddBreakpointFailed(id); + } +} + +void LldbEngineGuest::removeBreakpoint(BreakpointId id) +{ + DEBUG_FUNC_ENTER; + SYNC_INFERIOR_OR(notifyRemoveBreakpointFailed(id); return); + + lldb::SBBreakpoint llbp = m_breakpoints.take(id); + llbp.SetEnabled(false); + notifyRemoveBreakpointOk(id); +} + +void LldbEngineGuest::changeBreakpoint(BreakpointId id, + const Internal::BreakpointParameters &bp) +{ + DEBUG_FUNC_ENTER; + + // TODO + Q_UNUSED(id); + Q_UNUSED(bp); +} + +void LldbEngineGuest::selectThread(qint64 token) +{ + DEBUG_FUNC_ENTER; + SYNC_INFERIOR_OR(return); + + m_frame_to_file.clear(); + for (uint i = 0; i < m_process->GetNumThreads(); i++) { + lldb::SBThread t = m_process->GetThreadAtIndex(i); + if (t.GetThreadID() == token) { + m_currentThread = t; + StackFrames frames; + int firstResolvableFrame = -1; + for (uint j = 0; j < t.GetNumFrames(); j++) { + lldb::SBFrame fr = t.GetFrameAtIndex(j); + if (!fr.IsValid()) { + qDebug("warning: frame %i is garbage", j); + continue; + } + lldb::SBSymbolContext context = + fr.GetSymbolContext(lldb::eSymbolContextEverything); + lldb::SBSymbol sym = fr.GetSymbol(); + lldb::SBFunction func = fr.GetFunction(); + lldb::SBCompileUnit tu = fr.GetCompileUnit(); + lldb::SBModule module = fr.GetModule(); + lldb::SBBlock block = fr.GetBlock(); + lldb::SBBlock fblock = fr.GetFrameBlock(); + lldb::SBLineEntry le = fr.GetLineEntry(); + lldb::SBValueList values = fr.GetVariables(true, true, true, false); +#if 0 + qDebug()<<"\tframe "<\n" << fr.Disassemble() << "<--"; +#endif + + QString sourceFile; + QString sourceFilePath; + int lineNumber = 0; + if (le.IsValid()) { + lineNumber = le.GetLine(); + if (le.GetFileSpec().IsValid()) { + sourceFile = QString::fromLocal8Bit(le.GetFileSpec().GetFilename()); + sourceFilePath = QString::fromLocal8Bit(le.GetFileSpec().GetDirectory()) + + QLatin1String("/") + sourceFile; + if (firstResolvableFrame < 0) + firstResolvableFrame = j; + } + } + sourceFilePath = QFileInfo(sourceFilePath).canonicalFilePath(); + + QString functionName; + if (func.IsValid()) + functionName = QString::fromLocal8Bit(func.GetName()); + else + functionName = QString::fromLocal8Bit(sym.GetName()); + + StackFrame frame; + frame.level = fr.GetFrameID(); + if (func.IsValid()) + frame.function = QString::fromLocal8Bit(func.GetName()); + else + frame.function = QString::fromLocal8Bit(sym.GetName()); + frame.from = QString::fromLocal8Bit(module.GetFileSpec().GetFilename()); + frame.address = fr.GetPCAddress().GetLoadAddress(*m_target); + frame.line = lineNumber; + frame.file = sourceFilePath; + frame.usable = QFileInfo(frame.file).isReadable(); + frames.append(frame); + m_frame_to_file.insert(j, frame.file); + } + currentThreadChanged(token); + listFrames(frames); + activateFrame(firstResolvableFrame > -1 ? firstResolvableFrame : 0); + return; + } + } +} + +void LldbEngineGuest::updateThreads() +{ + DEBUG_FUNC_ENTER; + SYNC_INFERIOR_OR(return); + + /* There is no way to find the StopReason of a _process_ + * We try to emulate gdb here, by assuming there must be exactly one 'guilty' thread. + * However, if there are no threads at all, it must be that the process + * no longer exists. Let's tear down the whole session. + */ + if (m_process->GetNumThreads() < 1) { + notifyEngineSpontaneousShutdown(); + m_process->Kill(); + m_process->Destroy(); + } + + Threads threads; + for (uint i = 0; i < m_process->GetNumThreads(); i++) { + lldb::SBThread t = m_process->GetThreadAtIndex(i); + if (!t.IsValid()) { + qDebug("warning: thread %i is garbage", i); + continue; + } + ThreadData thread; + thread.id = t.GetThreadID(); + thread.targetId = QString::number(t.GetThreadID()); + thread.core.clear(); + thread.state = QString::number(t.GetStopReason()); + + switch (t.GetStopReason()) { + case lldb::eStopReasonInvalid: + case lldb::eStopReasonNone: + case lldb::eStopReasonTrace: + thread.state = QLatin1String("running"); + break; + case lldb::eStopReasonBreakpoint: + case lldb::eStopReasonWatchpoint: + showStatusMessage(QLatin1String("hit breakpoint")); + thread.state = QLatin1String("hit breakpoint"); + if (m_currentThread.GetThreadID() != t.GetThreadID()) { + m_currentThread = t; + currentThreadChanged(t.GetThreadID()); + m_relistFrames = true; + } + break; + case lldb::eStopReasonSignal: + showStatusMessage(QLatin1String("stopped")); + thread.state = QLatin1String("stopped"); + if (m_currentThread.GetThreadID() != t.GetThreadID()) { + m_currentThread = t; + currentThreadChanged(t.GetThreadID()); + m_relistFrames = true; + } + break; + case lldb::eStopReasonException: + showStatusMessage(QLatin1String("application crashed.")); + thread.state = QLatin1String("crashed"); + if (m_currentThread.GetThreadID() != t.GetThreadID()) { + m_currentThread = t; + currentThreadChanged(t.GetThreadID()); + m_relistFrames = true; + } + break; + case lldb::eStopReasonPlanComplete: + thread.state = QLatin1String("crazy things happened"); + break; + }; + + thread.lineNumber = 0; + thread.name = QString::fromLocal8Bit(t.GetName()); + + lldb::SBFrame fr = t.GetFrameAtIndex(0); + if (!fr.IsValid()) { + qDebug("warning: frame 0 is garbage"); + continue; + } + lldb::SBSymbolContext context = fr.GetSymbolContext(lldb::eSymbolContextEverything); + lldb::SBSymbol sym = fr.GetSymbol(); + lldb::SBFunction func = fr.GetFunction(); + lldb::SBLineEntry le = fr.GetLineEntry(); + QString sourceFile; + QString sourceFilePath; + int lineNumber = 0; + if (le.IsValid()) { + lineNumber = le.GetLine(); + if (le.GetFileSpec().IsValid()) { + sourceFile = QString::fromLocal8Bit(le.GetFileSpec().GetFilename()); + sourceFilePath = QString::fromLocal8Bit(le.GetFileSpec().GetDirectory()) + + QLatin1String("/") + sourceFile; + } + } + QString functionName; + if (func.IsValid()) + functionName = QString::fromLocal8Bit(func.GetName()); + else + functionName = QString::fromLocal8Bit(sym.GetName()); + + lldb::SBValueList values = fr.GetVariables(true, true, false, false); + thread.fileName = sourceFile; + thread.function = functionName; + thread.address = fr.GetPCAddress().GetLoadAddress(*m_target); + thread.lineNumber = lineNumber; + threads.append(thread); + } + listThreads(threads); + if (m_relistFrames) { + selectThread(m_currentThread.GetThreadID()); + m_relistFrames = false; + } +} + +void LldbEngineGuest::lldbEvent(lldb::SBEvent *ev) +{ + qDebug() << "lldbevent" << ev->GetType() << + m_process->GetState() << (int)state(); + + uint32_t etype = ev->GetType(); + switch (etype) { + // ProcessEvent + case 1: + switch (m_process->GetState()) { + case lldb::eStateRunning: // 5 + if (!m_running) + m_running = true; + notifyInferiorPid(m_process->GetProcessID()); + switch (state()) { + case EngineRunRequested: + notifyEngineRunAndInferiorRunOk(); + break; + case InferiorRunRequested: + notifyInferiorRunOk(); + break; + case InferiorStopOk: + notifyInferiorRunRequested(); + notifyInferiorRunOk(); + break; + default: + break; + } + break; + case lldb::eStateExited: // 9 + if (m_running) + m_running = false; + switch (state()) { + case InferiorShutdownRequested: + notifyInferiorShutdownOk(); + break; + case InferiorRunOk: + m_relistFrames = true; + updateThreads(); + notifyEngineSpontaneousShutdown(); + m_process->Kill(); + m_process->Destroy(); + break; + default: + updateThreads(); + break; + } + break; + case lldb::eStateStopped: // 4 + if (m_running) + m_running = false; + switch (state()) { + case InferiorShutdownRequested: + notifyInferiorShutdownOk(); + break; + case InferiorRunOk: + m_relistFrames = true; + updateThreads(); + notifyInferiorSpontaneousStop(); + // fall + default: + m_relistFrames = true; + updateThreads(); + break; + } + break; + case lldb::eStateCrashed: // 7 + if (m_running) + m_running = false; + switch (state()) { + case InferiorShutdownRequested: + notifyInferiorShutdownOk(); + break; + case InferiorRunOk: + m_relistFrames = true; + updateThreads(); + notifyInferiorSpontaneousStop(); + break; + default: + break; + } + break; + default: + qDebug("unexpected ProcessEvent"); + break; + } + break;; + default: + break;; + }; +} + + +} // namespace Internal +} // namespace Debugger diff --git a/src/plugins/debugger/lldblib/guest/lldbengineguest.h b/src/plugins/debugger/lldblib/guest/lldbengineguest.h new file mode 100644 index 0000000000..c11ac3f0a3 --- /dev/null +++ b/src/plugins/debugger/lldblib/guest/lldbengineguest.h @@ -0,0 +1,136 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** 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. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +****************************************************************************/ + +#ifndef DEBUGGER_LLDBENGINE_GUEST_H +#define DEBUGGER_LLDBENGINE_GUEST_H + +#include "ipcengineguest.h" + +#include +#include +#include +#include + +#include + +#if defined(HAVE_LLDB_PRIVATE) +#include "pygdbmiemu.h" +#endif + +Q_DECLARE_METATYPE (lldb::SBListener *) +Q_DECLARE_METATYPE (lldb::SBEvent *) + +namespace Debugger { +namespace Internal { + +class LldbEventListener : public QObject +{ +Q_OBJECT +public slots: + void listen(lldb::SBListener *listener); +signals: + // lldb API uses non thread safe implicit sharing with no explicit copy feature + // additionally the scope is undefined, hence this signal needs to be connected BlockingQueued + // whutever, works for now. + void lldbEvent(lldb::SBEvent *ev); +}; + + +class LldbEngineGuest : public IPCEngineGuest +{ + Q_OBJECT + +public: + explicit LldbEngineGuest(); + ~LldbEngineGuest(); + + void nuke(); + void setupEngine(); + void setupInferior(const QString &executable, const QStringList &arguments, + const QStringList &environment); + 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 ContextData &data); + void executeRunToFunction(const QString &functionName); + void executeJumpToLine(const ContextData &data); + void activateFrame(qint64); + void selectThread(qint64); + void disassemble(quint64 pc); + void addBreakpoint(BreakpointModelId id, const BreakpointParameters &bp); + void removeBreakpoint(BreakpointModelId id); + void changeBreakpoint(BreakpointModelId id, const BreakpointParameters &bp); + void requestUpdateWatchData(const WatchData &data, + const WatchUpdateFlags &flags); + void fetchFrameSource(qint64 frame); + +private: + bool m_running; + + QList m_arguments; + QList m_environment; + QThread m_wThread; + LldbEventListener *m_worker; + lldb::SBDebugger *m_lldb; + lldb::SBTarget *m_target; + lldb::SBProcess *m_process; + lldb::SBListener *m_listener; + + lldb::SBFrame m_currentFrame; + lldb::SBThread m_currentThread; + bool m_relistFrames; + QHash m_localesCache; + QHash m_breakpoints; + QHash m_frame_to_file; + + void updateThreads(); + void getWatchDataR(lldb::SBValue v, int level, + const QByteArray &p_iname, QList &wd); + +#if defined(HAVE_LLDB_PRIVATE) + PythonLLDBToGdbMiHack * py; +#endif + +private slots: + void lldbEvent(lldb::SBEvent *ev); +}; + +} // namespace Internal +} // namespace Debugger + +#endif // DEBUGGER_LLDBENGINE_H +#define SYNC_INFERIOR diff --git a/src/plugins/debugger/lldblib/guest/main.cpp b/src/plugins/debugger/lldblib/guest/main.cpp new file mode 100644 index 0000000000..9803a490f8 --- /dev/null +++ b/src/plugins/debugger/lldblib/guest/main.cpp @@ -0,0 +1,151 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** 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. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +****************************************************************************/ + +#include "lldbengineguest.h" + +#include +#include +#include +#include + +#include + +// #define DO_STDIO_DEBUG 1 +#ifdef DO_STDIO_DEBUG +#define D_STDIO0(x) qDebug(x) +#define D_STDIO1(x,a1) qDebug(x,a1) +#define D_STDIO2(x,a1,a2) qDebug(x,a1,a2) +#define D_STDIO3(x,a1,a2,a3) qDebug(x,a1,a2,a3) +#else +#define D_STDIO0(x) +#define D_STDIO1(x,a1) +#define D_STDIO2(x,a1,a2) +#define D_STDIO3(x,a1,a2,a3) +#endif + +class Stdio : public QIODevice +{ + Q_OBJECT +public: + QSocketNotifier notify; + Stdio() + : QIODevice() + , notify(fileno(stdin), QSocketNotifier::Read) + , buckethead(0) + { + setvbuf(stdin , NULL , _IONBF , 0); + setvbuf(stdout , NULL , _IONBF , 0); + setOpenMode(QIODevice::ReadWrite | QIODevice::Unbuffered); + connect(¬ify, SIGNAL(activated(int)), this, SLOT(activated())); + } + virtual qint64 bytesAvailable () const + { + qint64 r = QIODevice::bytesAvailable(); + foreach (const QByteArray &bucket, buckets) + r += bucket.size(); + r-= buckethead; + return r; + } + + virtual qint64 readData (char * data, qint64 maxSize) + { + D_STDIO1("readData %lli",maxSize); + qint64 size = maxSize; + while (size > 0) { + if (!buckets.size()) { + D_STDIO1("done prematurely with %lli", maxSize - size); + return maxSize - size; + } + QByteArray &bucket = buckets.head(); + if ((size + buckethead) >= bucket.size()) { + int d = bucket.size() - buckethead; + D_STDIO3("read (over bucket) d: %i buckethead: %i bucket.size(): %i", + d, buckethead, bucket.size()); + memcpy(data, bucket.data() + buckethead, d); + data += d; + size -= d; + buckets.dequeue(); + buckethead = 0; + } else { + D_STDIO1("read (in bucket) size: %lli", size); + memcpy(data, bucket.data() + buckethead, size); + data += size; + buckethead += size; + size = 0; + } + } + D_STDIO1("done with %lli",(maxSize - size)); + return maxSize - size; + } + + virtual qint64 writeData (const char * data, qint64 maxSize) + { + return ::write(fileno(stdout), data, maxSize); + } + + QQueue buckets; + int buckethead; + +private slots: + void activated() + { + QByteArray a; + a.resize(1000); + int ret = ::read(fileno(stdin), a.data(), 1000); + if (ret == 0) + ::exit(0); + assert(ret <= 1000); + D_STDIO1("activated %i", ret); + a.resize(ret); + buckets.enqueue(a); + emit readyRead(); + } +}; + +int main(int argc, char **argv) +{ + QCoreApplication app(argc, argv); + qDebug() << "guest engine operational"; + + Debugger::Internal::LldbEngineGuest lldb; + + + Stdio stdio; + lldb.setHostDevice(&stdio); + + return app.exec(); +} + +extern "C" { +extern const unsigned char lldbVersionString[] __attribute__ ((used)) = "@(#)PROGRAM:lldb PROJECT:lldb-26" "\n"; +extern const double lldbVersionNumber __attribute__ ((used)) = (double)26.; +extern const double LLDBVersionNumber __attribute__ ((used)) = (double)26.; +} + +#include "main.moc" diff --git a/src/plugins/debugger/lldblib/guest/qtcreator-lldb.plist b/src/plugins/debugger/lldblib/guest/qtcreator-lldb.plist new file mode 100644 index 0000000000..c0a3b2beaf --- /dev/null +++ b/src/plugins/debugger/lldblib/guest/qtcreator-lldb.plist @@ -0,0 +1,21 @@ + + + + + CFBundleDevelopmentRegion + English + CFBundleIdentifier + org.qt-project.qtcreator-lldb + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + Qt Creator LLDB Guest + CFBundleVersion + 1.0 + SecTaskAccess + + allowed + safe + + + diff --git a/src/plugins/debugger/lldblib/guest/qtcreator-lldb.pri b/src/plugins/debugger/lldblib/guest/qtcreator-lldb.pri new file mode 100644 index 0000000000..f44c3e9c84 --- /dev/null +++ b/src/plugins/debugger/lldblib/guest/qtcreator-lldb.pri @@ -0,0 +1,2 @@ +WITH_LLDB = $$(WITH_LLDB) +macx: !isEmpty(WITH_LLDB) : SUBDIRS += $$PWD/qtcreator-lldb.pro diff --git a/src/plugins/debugger/lldblib/guest/qtcreator-lldb.pro b/src/plugins/debugger/lldblib/guest/qtcreator-lldb.pro new file mode 100644 index 0000000000..847e31140c --- /dev/null +++ b/src/plugins/debugger/lldblib/guest/qtcreator-lldb.pro @@ -0,0 +1,61 @@ +WITH_LLDB = $$(WITH_LLDB) + +!macx: error (This can only be built on mac) +!exists($${WITH_LLDB}/include/lldb/lldb-enumerations.h): error(please see the README for build instructions) + +QT = core network + +include(../../../../../qtcreator.pri) +TEMPLATE = app +CONFIG -= app_bundle +CONFIG += debug +TARGET = qtcreator-lldb +DEPENDPATH += . .. ../.. ../../.. ../../../../libs +INCLUDEPATH += . .. ../.. ../../.. ../../../../libs +DESTDIR = $$IDE_LIBEXEC_PATH + +MOC_DIR=.tmp +OBJECTS_DIR=.tmp + +HEADERS += ../ipcengineguest.h \ + ../debuggerstreamops.h \ + ../breakpoint.h \ + ../watchdata.h \ + ../stackframe.h \ + ../disassemblerlines.h \ + lldbengineguest.h + +SOURCES += ../ipcengineguest.cpp \ + ../debuggerstreamops.cpp \ + ../breakpoint.cpp \ + ../watchdata.cpp \ + ../stackframe.cpp \ + ../disassemblerlines.cpp \ + lldbengineguest.cpp \ + main.cpp + + +LIBS += -sectcreate __TEXT __info_plist $$PWD/qtcreator-lldb.plist + +POSTL = rm -rf \'$${IDE_LIBEXEC_PATH}/LLDB.framework\' $$escape_expand(\\n\\t) \ + $$QMAKE_COPY_DIR $${WITH_LLDB}/build/Release/* \'$$IDE_LIBEXEC_PATH\' $$escape_expand(\\n\\t) \ + install_name_tool -change '@rpath/LLDB.framework/Versions/A/LLDB' '@executable_path/LLDB.framework/Versions/A/LLDB' $(TARGET) $$escape_expand(\\n\\t) \ + codesign -s lldb_codesign $(TARGET) + +!isEmpty(QMAKE_POST_LINK):QMAKE_POST_LINK = $$escape_expand(\\n\\t)$$QMAKE_POST_LINK +QMAKE_POST_LINK = $$POSTL $$QMAKE_POST_LINK +silent:QMAKE_POST_LINK = @echo signing $@ && $$QMAKE_POST_LINK + +LIBS += -framework Security -framework Python + +DEFINES += __STDC_LIMIT_MACROS __STDC_CONSTANT_MACROS + +INCLUDEPATH += $${WITH_LLDB}/include $${WITH_LLDB}/llvm/include/ +LIBS += -F$${WITH_LLDB}/build/Release -framework LLDB + +# include (lldb.pri) +# DEFINES += HAVE_LLDB_PRIVATE +# HEADERS += pygdbmiemu.h +# SOURCES += pygdbmiemu.cpp + + diff --git a/src/plugins/debugger/lldblib/ipcengineguest.cpp b/src/plugins/debugger/lldblib/ipcengineguest.cpp new file mode 100644 index 0000000000..50ebae4177 --- /dev/null +++ b/src/plugins/debugger/lldblib/ipcengineguest.cpp @@ -0,0 +1,637 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** 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. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +****************************************************************************/ + +#include "ipcengineguest.h" +#include "ipcenginehost.h" +#include "breakpoint.h" +#include "stackframe.h" +#include "threaddata.h" +#include "debuggerstreamops.h" + +#include + +#include + +#include +#include +#include +#include + +#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 *host) +{ + m_local_host = host; +} + +void IPCEngineGuest::setHostDevice(QIODevice *device) +{ + if (m_device) { + disconnect(m_device, SIGNAL(readyRead()), this, SLOT(readyRead())); + delete m_device; + } + m_device = device; + if (m_device) + connect(m_device, SIGNAL(readyRead()), SLOT(readyRead())); +} + +void IPCEngineGuest::rpcCall(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'); + QLocalSocket *sock = qobject_cast(m_device); + if (sock) + sock->flush(); + } +} + +void IPCEngineGuest::readyRead() +{ + if (!m_nextMessagePayloadSize) { + if (quint64(m_device->bytesAvailable()) < 3 * sizeof(quint64)) + 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')) { + qDebug("IPC Error: corrupted frame"); + showMessage(QLatin1String("[guest] IPC Error: corrupted frame"), LogError); + nuke(); + return; + } + payload.chop(1); + rpcCallback(m_nextMessageFunction, payload); + m_nextMessagePayloadSize = 0; + + if (quint64(m_device->bytesAvailable ()) >= 3 * sizeof(quint64)) + QTimer::singleShot(0, this, SLOT(readyRead())); +} + +void IPCEngineGuest::rpcCallback(quint64 f, QByteArray payload) +{ + switch (f) { + default: + qDebug("IPC Error: unhandled id in host to guest call"); + showMessage(QLatin1String("IPC Error: unhandled id in host to guest call"), LogError); + nuke(); + 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); + ContextData data; + s >> data.fileName; + s >> data.lineNumber; + executeRunToLine(data); + } + 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); + ContextData data; + s >> data.fileName; + s >> data.lineNumber; + executeJumpToLine(data); + } + 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); + BreakpointModelId id; + BreakpointParameters d; + s >> id; + s >> d; + addBreakpoint(id, d); + } + break; + case IPCEngineHost::RemoveBreakpoint: + { + QDataStream s(payload); + SET_NATIVE_BYTE_ORDER(s); + BreakpointModelId id; + s >> id; + removeBreakpoint(id); + } + break; + case IPCEngineHost::ChangeBreakpoint: + { + QDataStream s(payload); + SET_NATIVE_BYTE_ORDER(s); + BreakpointModelId id; + BreakpointParameters d; + s >> id; + s >> d; + changeBreakpoint(id, d); + } + break; + case IPCEngineHost::RequestUpdateWatchData: + { + QDataStream s(payload); + SET_NATIVE_BYTE_ORDER(s); + WatchData data; + s >> data; + requestUpdateWatchData(data); + } + break; + case IPCEngineHost::FetchFrameSource: + { + QDataStream s(payload); + SET_NATIVE_BYTE_ORDER(s); + qint64 id; + s >> id; + fetchFrameSource(id); + } + 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 DisassemblerLines &da) +{ + QByteArray p; + { + QDataStream s(&p, QIODevice::WriteOnly); + SET_NATIVE_BYTE_ORDER(s); + s << pc; + s << da; + } + rpcCall(Disassembled, p); +} + +void IPCEngineGuest::notifyAddBreakpointOk(BreakpointModelId id) +{ + QByteArray p; + { + QDataStream s(&p, QIODevice::WriteOnly); + SET_NATIVE_BYTE_ORDER(s); + s << id; + } + rpcCall(NotifyAddBreakpointOk, p); +} + +void IPCEngineGuest::notifyAddBreakpointFailed(BreakpointModelId id) +{ + QByteArray p; + { + QDataStream s(&p, QIODevice::WriteOnly); + SET_NATIVE_BYTE_ORDER(s); + s << id; + } + rpcCall(NotifyAddBreakpointFailed, p); +} + +void IPCEngineGuest::notifyRemoveBreakpointOk(BreakpointModelId id) +{ + QByteArray p; + { + QDataStream s(&p, QIODevice::WriteOnly); + SET_NATIVE_BYTE_ORDER(s); + s << id; + } + rpcCall(NotifyRemoveBreakpointOk, p); +} + +void IPCEngineGuest::notifyRemoveBreakpointFailed(BreakpointModelId id) +{ + QByteArray p; + { + QDataStream s(&p, QIODevice::WriteOnly); + SET_NATIVE_BYTE_ORDER(s); + s << id; + } + rpcCall(NotifyRemoveBreakpointFailed, p); +} + +void IPCEngineGuest::notifyChangeBreakpointOk(BreakpointModelId id) +{ + QByteArray p; + { + QDataStream s(&p, QIODevice::WriteOnly); + SET_NATIVE_BYTE_ORDER(s); + s << id; + } + rpcCall(NotifyChangeBreakpointOk, p); +} + +void IPCEngineGuest::notifyChangeBreakpointFailed(BreakpointModelId id) +{ + QByteArray p; + { + QDataStream s(&p, QIODevice::WriteOnly); + SET_NATIVE_BYTE_ORDER(s); + s << id; + } + rpcCall(NotifyChangeBreakpointFailed, p); +} + +void IPCEngineGuest::notifyBreakpointAdjusted(BreakpointModelId id, + const BreakpointParameters &bp) +{ + QByteArray p; + { + QDataStream s(&p, QIODevice::WriteOnly); + SET_NATIVE_BYTE_ORDER(s); + s << id << bp; + } + rpcCall(NotifyBreakpointAdjusted, p); +} + +void IPCEngineGuest::updateWatchData(bool fullCycle, const QList &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); +} + +void IPCEngineGuest::frameSourceFetched(qint64 id, const QString &name, const QString &source) +{ + QByteArray p; + { + QDataStream s(&p, QIODevice::WriteOnly); + SET_NATIVE_BYTE_ORDER(s); + s << id; + s << name; + s << source; + } + rpcCall(FrameSourceFetched, p); +} + +} // namespace Internal +} // namespace Debugger + + diff --git a/src/plugins/debugger/lldblib/ipcengineguest.h b/src/plugins/debugger/lldblib/ipcengineguest.h new file mode 100644 index 0000000000..671e49028d --- /dev/null +++ b/src/plugins/debugger/lldblib/ipcengineguest.h @@ -0,0 +1,191 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** 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. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +****************************************************************************/ + +#ifndef DEBUGGER_IPCENGINE_H +#define DEBUGGER_IPCENGINE_H + +#include "breakhandler.h" +#include "debuggerengine.h" +#include "disassemblerlines.h" +#include "stackhandler.h" +#include "threadshandler.h" + +#include +#include +#include + +namespace Debugger { +namespace Internal { + +class IPCEngineHost; +class IPCEngineGuest : public QObject +{ + Q_OBJECT + +public: + IPCEngineGuest(); + virtual ~IPCEngineGuest(); + + void setLocalHost(IPCEngineHost *); + void setHostDevice(QIODevice *); + + virtual void nuke() = 0; + 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 ContextData &data) = 0; + virtual void executeRunToFunction(const QString &functionName) = 0; + virtual void executeJumpToLine(const ContextData &data) = 0; + virtual void activateFrame(qint64 token) = 0; + virtual void selectThread(qint64 token) = 0; + virtual void disassemble(quint64 pc) = 0; + virtual void addBreakpoint(BreakpointModelId id, const BreakpointParameters &bp) = 0; + virtual void removeBreakpoint(BreakpointModelId id) = 0; + virtual void changeBreakpoint(BreakpointModelId id, const BreakpointParameters &bp) = 0; + virtual void requestUpdateWatchData(const WatchData &data, + const WatchUpdateFlags & flags = WatchUpdateFlags()) = 0; + virtual void fetchFrameSource(qint64 frame) = 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, + FrameSourceFetched = 48 + }; + 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 = quint64(-1)); + void showStatusMessage(const QString &msg, quint64 timeout = quint64(-1)); + + void currentFrameChanged(qint64 token); + void currentThreadChanged(qint64 token); + void listFrames(const StackFrames &); + void listThreads(const Threads &); + void disassembled(quint64 pc, const DisassemblerLines &da); + + void notifyAddBreakpointOk(BreakpointModelId id); + void notifyAddBreakpointFailed(BreakpointModelId id); + void notifyRemoveBreakpointOk(BreakpointModelId id); + void notifyRemoveBreakpointFailed(BreakpointModelId id); + void notifyChangeBreakpointOk(BreakpointModelId id); + void notifyChangeBreakpointFailed(BreakpointModelId id); + void notifyBreakpointAdjusted(BreakpointModelId id, const BreakpointParameters &bp); + + void updateWatchData(bool fullCycle, const QList &); + + void frameSourceFetched(qint64 frame, const QString &name, const QString &sourceCode); + + 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/lldblib/ipcenginehost.cpp b/src/plugins/debugger/lldblib/ipcenginehost.cpp new file mode 100644 index 0000000000..0562939916 --- /dev/null +++ b/src/plugins/debugger/lldblib/ipcenginehost.cpp @@ -0,0 +1,661 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** 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. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +****************************************************************************/ + +#include "ipcenginehost.h" + +#include "ipcengineguest.h" +#include "debuggerstartparameters.h" +#include "breakhandler.h" +#include "breakpoint.h" +#include "disassemblerlines.h" +#include "moduleshandler.h" +#include "registerhandler.h" +#include "stackhandler.h" +#include "watchhandler.h" +#include "watchutils.h" +#include "threadshandler.h" +#include "disassembleragent.h" +#include "memoryagent.h" +#include "debuggerstreamops.h" +#include "debuggercore.h" + +#include + +#include +#include +#include +#include +#include + +#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_localGuest(0) + , m_nextMessagePayloadSize(0) + , m_cookie(1) + , m_device(0) +{ + connect(this, SIGNAL(stateChanged(Debugger::DebuggerState)), SLOT(m_stateChanged(Debugger::DebuggerState))); +} + +IPCEngineHost::~IPCEngineHost() +{ + delete m_device; +} + +void IPCEngineHost::setLocalGuest(IPCEngineGuest *guest) +{ + m_localGuest = guest; +} + +void IPCEngineHost::setGuestDevice(QIODevice *device) +{ + if (m_device) { + disconnect(m_device, SIGNAL(readyRead()), this, SLOT(readyRead())); + delete m_device; + } + m_device = device; + 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.toStringList(); + } + 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 ContextData &data) +{ + QByteArray p; + { + QDataStream s(&p, QIODevice::WriteOnly); + SET_NATIVE_BYTE_ORDER(s); + s << data.fileName; + s << quint64(data.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 ContextData &data) +{ + QByteArray p; + { + QDataStream s(&p, QIODevice::WriteOnly); + SET_NATIVE_BYTE_ORDER(s); + s << data.fileName; + s << quint64(data.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(ThreadId id) +{ + resetLocation(); + QTC_ASSERT(id.isValid(), return); + QByteArray p; + { + QDataStream s(&p, QIODevice::WriteOnly); + SET_NATIVE_BYTE_ORDER(s); + s << id.raw(); + } + rpcCall(SelectThread, p); +} + +void IPCEngineHost::fetchDisassembler(DisassemblerAgent *v) +{ + quint64 address = v->location().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::insertBreakpoint(BreakpointModelId id) +{ + breakHandler()->notifyBreakpointInsertProceeding(id); + QByteArray p; + { + QDataStream s(&p, QIODevice::WriteOnly); + SET_NATIVE_BYTE_ORDER(s); + s << id; + s << breakHandler()->breakpointData(id); + } + rpcCall(AddBreakpoint, p); +} + +void IPCEngineHost::removeBreakpoint(BreakpointModelId id) +{ + breakHandler()->notifyBreakpointRemoveProceeding(id); + QByteArray p; + { + QDataStream s(&p, QIODevice::WriteOnly); + SET_NATIVE_BYTE_ORDER(s); + s << id; + } + rpcCall(RemoveBreakpoint, p); +} + +void IPCEngineHost::changeBreakpoint(BreakpointModelId id) +{ + breakHandler()->notifyBreakpointChangeProceeding(id); + QByteArray p; + { + QDataStream s(&p, QIODevice::WriteOnly); + SET_NATIVE_BYTE_ORDER(s); + s << id; + s << breakHandler()->breakpointData(id); + } + rpcCall(RemoveBreakpoint, p); +} + +void IPCEngineHost::updateWatchData(const WatchData &data, + const WatchUpdateFlags &flags) +{ + Q_UNUSED(flags); + QByteArray p; + { + QDataStream s(&p, QIODevice::WriteOnly); + SET_NATIVE_BYTE_ORDER(s); + s << data; + } + rpcCall(RequestUpdateWatchData, p); +} + +void IPCEngineHost::fetchFrameSource(qint64 id) +{ + QByteArray p; + { + QDataStream s(&p, QIODevice::WriteOnly); + SET_NATIVE_BYTE_ORDER(s); + s << id; + } + rpcCall(FetchFrameSource, p); +} + +void IPCEngineHost::rpcCallback(quint64 f, QByteArray payload) +{ + switch (f) { + default: { + showMessage(QLatin1String("IPC Error: unhandled id in guest to host call")); + const QString logMessage = tr("Fatal engine shutdown. Incompatible binary or IPC error."); + showMessage(logMessage, LogError); + showStatusMessage(logMessage); + } + nuke(); + 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); + if (!sh->currentFrame().isUsable() || QFileInfo(sh->currentFrame().file).exists()) + gotoLocation(Location(sh->currentFrame(), true)); + else if (!m_sourceAgents.contains(sh->currentFrame().file)) + fetchFrameSource(token); + foreach (SourceAgent *agent, m_sourceAgents.values()) + agent->updateLocationMarker(); + } + break; + case IPCEngineGuest::CurrentThreadChanged: + { + QDataStream s(payload); + SET_NATIVE_BYTE_ORDER(s); + quint64 token; + s >> token; + threadsHandler()->setCurrentThread(ThreadId(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; + DisassemblerLines lines; + s >> pc; + s >> lines; + DisassemblerAgent *view = m_frameToDisassemblerAgent.take(pc); + if (view) + view->setContents(lines); + } + break; + case IPCEngineGuest::UpdateWatchData: + { + QDataStream s(payload); + SET_NATIVE_BYTE_ORDER(s); + bool fullCycle; + qint64 count; + QList 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->insertData(wd); + } + break; + case IPCEngineGuest::NotifyAddBreakpointOk: + { + attemptBreakpointSynchronization(); + QDataStream s(payload); + SET_NATIVE_BYTE_ORDER(s); + quint64 d; + s >> d; + BreakpointModelId id = BreakpointModelId::fromInternalId(d); + breakHandler()->notifyBreakpointInsertOk(id); + } + break; + case IPCEngineGuest::NotifyAddBreakpointFailed: + { + QDataStream s(payload); + SET_NATIVE_BYTE_ORDER(s); + quint64 d; + s >> d; + BreakpointModelId id = BreakpointModelId::fromInternalId(d); + breakHandler()->notifyBreakpointInsertFailed(id); + } + break; + case IPCEngineGuest::NotifyRemoveBreakpointOk: + { + QDataStream s(payload); + SET_NATIVE_BYTE_ORDER(s); + quint64 d; + s >> d; + BreakpointModelId id = BreakpointModelId::fromInternalId(d); + breakHandler()->notifyBreakpointRemoveOk(id); + } + break; + case IPCEngineGuest::NotifyRemoveBreakpointFailed: + { + QDataStream s(payload); + SET_NATIVE_BYTE_ORDER(s); + quint64 d; + s >> d; + BreakpointModelId id = BreakpointModelId::fromInternalId(d); + breakHandler()->notifyBreakpointRemoveFailed(id); + } + break; + case IPCEngineGuest::NotifyChangeBreakpointOk: + { + QDataStream s(payload); + SET_NATIVE_BYTE_ORDER(s); + quint64 d; + s >> d; + BreakpointModelId id = BreakpointModelId::fromInternalId(d); + breakHandler()->notifyBreakpointChangeOk(id); + } + break; + case IPCEngineGuest::NotifyChangeBreakpointFailed: + { + QDataStream s(payload); + SET_NATIVE_BYTE_ORDER(s); + quint64 d; + s >> d; + BreakpointModelId id = BreakpointModelId::fromInternalId(d); + breakHandler()->notifyBreakpointChangeFailed(id); + } + break; + case IPCEngineGuest::NotifyBreakpointAdjusted: + { + QDataStream s(payload); + SET_NATIVE_BYTE_ORDER(s); + quint64 dd; + BreakpointParameters d; + s >> dd >> d; + BreakpointModelId id = BreakpointModelId::fromInternalId(dd); + breakHandler()->notifyBreakpointAdjusted(id, d); + } + break; + case IPCEngineGuest::FrameSourceFetched: + { + QDataStream s(payload); + SET_NATIVE_BYTE_ORDER(s); + qint64 token; + QString path; + QString source; + s >> token >> path >> source; + SourceAgent *agent = new SourceAgent(this); + agent->setSourceProducerName(startParameters().connParams.host); + agent->setContent(path, source); + m_sourceAgents.insert(path, agent); + agent->updateLocationMarker(); + } + break; + } +} + +void IPCEngineHost::m_stateChanged(Debugger::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_localGuest) { + QMetaObject::invokeMethod(m_localGuest, + "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'); + QLocalSocket *sock = qobject_cast(m_device); + if (sock) + sock->flush(); + } +} + +void IPCEngineHost::readyRead() +{ + QDataStream s(m_device); + SET_NATIVE_BYTE_ORDER(s); + if (!m_nextMessagePayloadSize) { + if (quint64(m_device->bytesAvailable ()) < 3 * sizeof(quint64)) + 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")); + nuke(); + return; + } + rpcCallback(m_nextMessageFunction, payload); + m_nextMessagePayloadSize = 0; + if (quint64(m_device->bytesAvailable()) >= 3 * sizeof(quint64)) + QTimer::singleShot(0, this, SLOT(readyRead())); +} + +} // namespace Internal +} // namespace Debugger + + diff --git a/src/plugins/debugger/lldblib/ipcenginehost.h b/src/plugins/debugger/lldblib/ipcenginehost.h new file mode 100644 index 0000000000..8364d50657 --- /dev/null +++ b/src/plugins/debugger/lldblib/ipcenginehost.h @@ -0,0 +1,140 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** 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. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +****************************************************************************/ + +#ifndef DEBUGGER_IPCENGINE_HOST_H +#define DEBUGGER_IPCENGINE_HOST_H + +#include "debuggerengine.h" +#include "threadshandler.h" +#include "stackhandler.h" +#include "breakhandler.h" +#include "sourceagent.h" + +#include +#include +#include + +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, + FetchFrameSource = 26 + }; + 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 ContextData &data); + void executeRunToFunction(const QString &functionName); + void executeJumpToLine(const ContextData &data); + void activateFrame(int index); + void selectThread(ThreadId index); + void fetchDisassembler(DisassemblerAgent *); + bool acceptsBreakpoint(BreakpointModelId) const { return true; } // FIXME + void insertBreakpoint(BreakpointModelId id); + void removeBreakpoint(BreakpointModelId id); + void changeBreakpoint(BreakpointModelId id); + void updateWatchData(const WatchData &data, + const WatchUpdateFlags &flags = WatchUpdateFlags()); + void fetchFrameSource(qint64 id); + bool hasCapability(unsigned) const { return false; } + + void rpcCall(Function f, QByteArray payload = QByteArray()); +protected: + virtual void nuke() = 0; +public slots: + void rpcCallback(quint64 f, QByteArray payload = QByteArray()); +private slots: + void m_stateChanged(Debugger::DebuggerState state); + void readyRead(); +private: + IPCEngineGuest *m_localGuest; + quint64 m_nextMessageCookie; + quint64 m_nextMessageFunction; + quint64 m_nextMessagePayloadSize; + quint64 m_cookie; + QIODevice *m_device; + QHash m_frameToDisassemblerAgent; + QHash m_sourceAgents; +}; + +} // namespace Internal +} // namespace Debugger + +#endif // DEBUGGER_LLDBENGINE_H diff --git a/src/plugins/debugger/lldblib/lldbenginehost.cpp b/src/plugins/debugger/lldblib/lldbenginehost.cpp new file mode 100644 index 0000000000..2bac195eb2 --- /dev/null +++ b/src/plugins/debugger/lldblib/lldbenginehost.cpp @@ -0,0 +1,232 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** 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. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +****************************************************************************/ + +#include "lldbenginehost.h" + +#include "debuggerstartparameters.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 "disassembleragent.h" +#include "memoryagent.h" + +#include +#include + +#include +#include +#include +#include +#include + +namespace Debugger { +namespace Internal { + +SshIODevice::SshIODevice(QSsh::SshRemoteProcessRunner *r) + : runner(r) + , buckethead(0) +{ + setOpenMode(QIODevice::ReadWrite | QIODevice::Unbuffered); + connect (runner, SIGNAL(processStarted()), this, SLOT(processStarted())); + connect(runner, SIGNAL(readyReadStandardOutput()), this, SLOT(outputAvailable())); + connect(runner, SIGNAL(readyReadStandardError()), this, SLOT(errorOutputAvailable())); +} + +SshIODevice::~SshIODevice() +{ + delete runner; +} + +qint64 SshIODevice::bytesAvailable () const +{ + qint64 r = QIODevice::bytesAvailable(); + foreach (const QByteArray &bucket, buckets) + r += bucket.size(); + r-= buckethead; + return r; +} +qint64 SshIODevice::writeData (const char * data, qint64 maxSize) +{ + if (proc == 0) { + startupbuffer += QByteArray::fromRawData(data, maxSize); + return maxSize; + } + proc->write(data, maxSize); + return maxSize; +} +qint64 SshIODevice::readData (char * data, qint64 maxSize) +{ + if (proc == 0) + return 0; + qint64 size = maxSize; + while (size > 0) { + if (!buckets.size()) + return maxSize - size; + QByteArray &bucket = buckets.head(); + if ((size + buckethead) >= bucket.size()) { + int d = bucket.size() - buckethead; + memcpy(data, bucket.data() + buckethead, d); + data += d; + size -= d; + buckets.dequeue(); + buckethead = 0; + } else { + memcpy(data, bucket.data() + buckethead, size); + data += size; + buckethead += size; + size = 0; + } + } + return maxSize - size; +} + +void SshIODevice::processStarted() +{ + runner->writeDataToProcess(startupbuffer); +} + +void SshIODevice::outputAvailable() +{ + buckets.enqueue(runner->readAllStandardOutput()); + emit readyRead(); +} + +void SshIODevice::errorOutputAvailable() +{ + fprintf(stderr, "%s", runner->readAllStandardError().data()); +} + + +LldbEngineHost::LldbEngineHost(const DebuggerStartParameters &startParameters) + :IPCEngineHost(startParameters), m_ssh(0) +{ + showMessage(QLatin1String("setting up coms")); + setObjectName(QLatin1String("LLDBEngine")); + + if (startParameters.startMode == StartRemoteEngine) + { + m_guestProcess = 0; + QSsh::SshRemoteProcessRunner * const runner = new QSsh::SshRemoteProcessRunner; + connect (runner, SIGNAL(connectionError(QSsh::SshError)), + this, SLOT(sshConnectionError(QSsh::SshError))); + runner->run(startParameters.serverStartScript.toUtf8(), startParameters.connParams); + setGuestDevice(new SshIODevice(runner)); + } else { + m_guestProcess = new QProcess(this); + + connect(m_guestProcess, SIGNAL(finished(int,QProcess::ExitStatus)), + this, SLOT(finished(int,QProcess::ExitStatus))); + + connect(m_guestProcess, SIGNAL(readyReadStandardError()), this, + SLOT(stderrReady())); + + + QString a = Core::ICore::resourcePath() + QLatin1String("/qtcreator-lldb"); + if (getenv("QTC_LLDB_GUEST") != 0) + a = QString::fromLocal8Bit(getenv("QTC_LLDB_GUEST")); + + showStatusMessage(QString(QLatin1String("starting %1")).arg(a)); + + m_guestProcess->start(a, QStringList(), QIODevice::ReadWrite | QIODevice::Unbuffered); + m_guestProcess->setReadChannel(QProcess::StandardOutput); + + if (!m_guestProcess->waitForStarted()) { + showStatusMessage(tr("qtcreator-lldb failed to start: %1").arg(m_guestProcess->errorString())); + notifyEngineSpontaneousShutdown(); + return; + } + + setGuestDevice(m_guestProcess); + } +} + +LldbEngineHost::~LldbEngineHost() +{ + showMessage(QLatin1String("tear down qtcreator-lldb")); + + if (m_guestProcess) { + disconnect(m_guestProcess, SIGNAL(finished(int,QProcess::ExitStatus)), + this, SLOT(finished(int,QProcess::ExitStatus))); + + + m_guestProcess->terminate(); + m_guestProcess->kill(); + } + if (m_ssh && m_ssh->isProcessRunning()) { + // TODO: openssh doesn't do that + + m_ssh->sendSignalToProcess(QSsh::SshRemoteProcess::KillSignal); + } +} + +void LldbEngineHost::nuke() +{ + stderrReady(); + showMessage(QLatin1String("Nuke engaged. Bug in Engine/IPC or incompatible IPC versions. "), LogError); + showStatusMessage(tr("Fatal engine shutdown. Consult debugger log for details.")); + m_guestProcess->terminate(); + m_guestProcess->kill(); + notifyEngineSpontaneousShutdown(); +} +void LldbEngineHost::sshConnectionError(QSsh::SshError e) +{ + showStatusMessage(tr("SSH connection error: %1").arg(e)); +} + +void LldbEngineHost::finished(int, QProcess::ExitStatus status) +{ + showMessage(QString(QLatin1String("guest went bye bye. exit status: %1 and code: %2")) + .arg(status).arg(m_guestProcess->exitCode()), LogError); + nuke(); +} + +void LldbEngineHost::stderrReady() +{ + fprintf(stderr,"%s", m_guestProcess->readAllStandardError().data()); +} + +DebuggerEngine *createLldbEngine(const DebuggerStartParameters &startParameters) +{ + return new LldbEngineHost(startParameters); +} + +} // namespace Internal +} // namespace Debugger + diff --git a/src/plugins/debugger/lldblib/lldbenginehost.h b/src/plugins/debugger/lldblib/lldbenginehost.h new file mode 100644 index 0000000000..52df2b373e --- /dev/null +++ b/src/plugins/debugger/lldblib/lldbenginehost.h @@ -0,0 +1,88 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** 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. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +****************************************************************************/ + +#ifndef DEBUGGER_LLDBENGINE_HOST_H +#define DEBUGGER_LLDBENGINE_HOST_H + +#include "ipcenginehost.h" +#include +#include +#include +#include + +#include +#include + +namespace Debugger { +namespace Internal { + +class SshIODevice : public QIODevice +{ +Q_OBJECT +public: + SshIODevice(QSsh::SshRemoteProcessRunner *r); + ~SshIODevice(); + virtual qint64 bytesAvailable () const; + virtual qint64 writeData (const char * data, qint64 maxSize); + virtual qint64 readData (char * data, qint64 maxSize); +private slots: + void processStarted(); + void outputAvailable(); + void errorOutputAvailable(); +private: + QSsh::SshRemoteProcessRunner *runner; + QSsh::SshRemoteProcess::Ptr proc; + int buckethead; + QQueue buckets; + QByteArray startupbuffer; +}; + +class LldbEngineHost : public IPCEngineHost +{ + Q_OBJECT + +public: + explicit LldbEngineHost(const DebuggerStartParameters &startParameters); + ~LldbEngineHost(); + +private: + QProcess *m_guestProcess; + QSsh::SshRemoteProcessRunner *m_ssh; +protected: + void nuke(); +private slots: + void sshConnectionError(QSsh::SshError); + void finished(int, QProcess::ExitStatus); + void stderrReady(); +}; + +} // namespace Internal +} // namespace Debugger + +#endif // DEBUGGER_LLDBENGINE_HOST_H diff --git a/src/plugins/debugger/lldblib/lldbhost.pri b/src/plugins/debugger/lldblib/lldbhost.pri new file mode 100644 index 0000000000..0e9297d7e3 --- /dev/null +++ b/src/plugins/debugger/lldblib/lldbhost.pri @@ -0,0 +1,20 @@ +WITH_LLDB = $$(WITH_LLDB) + +HEADERS += $$PWD/ipcenginehost.h \ + $$PWD/lldbenginehost.h + +SOURCES += $$PWD/ipcenginehost.cpp \ + $$PWD/lldbenginehost.cpp + +INCLUDEPATH+= + +FORMS += + +RESOURCES += + +!isEmpty(WITH_LLDB) { + DEFINES += WITH_LLDB + HEADERS += $$PWD/lldboptionspage.h + SOURCES += $$PWD/lldboptionspage.cpp + FORMS += $$PWD/lldboptionspagewidget.ui +} diff --git a/src/plugins/debugger/lldblib/lldboptionspage.cpp b/src/plugins/debugger/lldblib/lldboptionspage.cpp new file mode 100644 index 0000000000..9fe0cb2a30 --- /dev/null +++ b/src/plugins/debugger/lldblib/lldboptionspage.cpp @@ -0,0 +1,109 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** 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. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +****************************************************************************/ + +#include "lldboptionspage.h" +#include "debuggerconstants.h" +#include "debuggerinternalconstants.h" + +#include + +#include +#include +#include +#include +#include + +namespace Debugger { +namespace Internal { + +LldbOptionsPageWidget::LldbOptionsPageWidget(QWidget *parent, QSettings *s_) + : QWidget(parent) + , s(s_) +{ + m_ui.setupUi(this); + load(); +} + +void LldbOptionsPageWidget::save() +{ + s->beginGroup(QLatin1String("LLDB")); + s->setValue(QLatin1String("enabled"), m_ui.enableLldb->isChecked ()); + s->setValue(QLatin1String("gdbEmu"), m_ui.gdbEmu->isChecked ()); + s->endGroup(); +} + +void LldbOptionsPageWidget::load() +{ + s->beginGroup(QLatin1String("LLDB")); + m_ui.enableLldb->setChecked(s->value(QLatin1String("enabled"), false).toBool()); + m_ui.gdbEmu->setChecked(s->value(QLatin1String("gdbEmu"), true).toBool()); + s->endGroup(); +} + +// ---------- LldbOptionsPage +LldbOptionsPage::LldbOptionsPage() +{ + // m_options->fromSettings(Core::ICore::settings()); + setId(QLatin1String("F.Lldb")); + setDisplayName(tr("LLDB")); + setCategory(Debugger::Constants::DEBUGGER_SETTINGS_CATEGORY); + setDisplayCategory(QCoreApplication::translate("Debugger", Constants::DEBUGGER_SETTINGS_TR_CATEGORY)); + setCategoryIcon(QIcon(QLatin1String(Constants::DEBUGGER_COMMON_SETTINGS_CATEGORY_ICON))); +} + +QWidget *LldbOptionsPage::createPage(QWidget *parent) +{ + m_widget = new LldbOptionsPageWidget(parent, Core::ICore::settings()); + return m_widget; +} + +void LldbOptionsPage::apply() +{ + if (!m_widget) + return; + m_widget->save(); +} + +void LldbOptionsPage::finish() +{ +} + +bool LldbOptionsPage::matches(const QString &s) const +{ + return QString(s.toLower()).contains("lldb"); +} + +void addLldbOptionPages(QList *opts) +{ + opts->push_back(new LldbOptionsPage); +} + + +} // namespace Internal +} // namespace Debugger diff --git a/src/plugins/debugger/lldblib/lldboptionspage.h b/src/plugins/debugger/lldblib/lldboptionspage.h new file mode 100644 index 0000000000..78cd3c7e67 --- /dev/null +++ b/src/plugins/debugger/lldblib/lldboptionspage.h @@ -0,0 +1,80 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** 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. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +****************************************************************************/ + +#ifndef LLDBSETTINGSPAGE_H +#define LLDBSETTINGSPAGE_H + +#include +#include "ui_lldboptionspagewidget.h" + +#include +#include +#include +#include + +namespace Debugger { +namespace Internal { + +class LldbOptionsPageWidget : public QWidget +{ + Q_OBJECT + +public: + explicit LldbOptionsPageWidget(QWidget *parent, QSettings *s); + +public slots: + void save(); + void load(); + +private: + Ui::LldbOptionsPageWidget m_ui; + QSettings *s; +}; + +class LldbOptionsPage : public Core::IOptionsPage +{ + Q_OBJECT + +public: + LldbOptionsPage(); + + // IOptionsPage + QWidget *createPage(QWidget *parent); + void apply(); + void finish(); + bool matches(const QString &) const; + +private: + QPointer m_widget; +}; + +} // namespace Internal +} // namespace Debugger + +#endif // LLDBSETTINGSPAGE_H diff --git a/src/plugins/debugger/lldblib/lldboptionspagewidget.ui b/src/plugins/debugger/lldblib/lldboptionspagewidget.ui new file mode 100644 index 0000000000..78e77699f0 --- /dev/null +++ b/src/plugins/debugger/lldblib/lldboptionspagewidget.ui @@ -0,0 +1,59 @@ + + + Debugger::Internal::LldbOptionsPageWidget + + + + 0 + 0 + 522 + 512 + + + + + + + + + + Enable LLDB + + + true + + + false + + + + + + Use GDB Python dumpers + + + false + + + + + + + + + + Qt::Vertical + + + + 20 + 203 + + + + + + + + + -- cgit v1.2.1