forked from qt-creator/qt-creator
Debugger: Remove LldbLibEngine
That's dead code now that we go with the Python interface. Change-Id: Ie10393d6adf5d25540c4082aeccf683e88bcdc89 Reviewed-by: hjk <hjk121@nokiamail.com>
This commit is contained in:
@@ -151,7 +151,6 @@ include(cdb/cdb.pri)
|
|||||||
include(gdb/gdb.pri)
|
include(gdb/gdb.pri)
|
||||||
include(pdb/pdb.pri)
|
include(pdb/pdb.pri)
|
||||||
include(lldb/lldb.pri)
|
include(lldb/lldb.pri)
|
||||||
include(lldblib/lldbhost.pri)
|
|
||||||
include(qml/qml.pri)
|
include(qml/qml.pri)
|
||||||
include(namedemangler/namedemangler.pri)
|
include(namedemangler/namedemangler.pri)
|
||||||
|
|
||||||
|
|||||||
@@ -131,16 +131,6 @@ QtcPlugin {
|
|||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
Group {
|
|
||||||
name: "lldblib"
|
|
||||||
id: lldblib
|
|
||||||
prefix: "lldblib/"
|
|
||||||
files: [
|
|
||||||
"ipcenginehost.cpp", "ipcenginehost.h",
|
|
||||||
"lldbenginehost.cpp", "lldbenginehost.h"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
|
|
||||||
Group {
|
Group {
|
||||||
name: "pdb"
|
name: "pdb"
|
||||||
prefix: "pdb/"
|
prefix: "pdb/"
|
||||||
@@ -247,16 +237,6 @@ QtcPlugin {
|
|||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
Group {
|
|
||||||
name: "LLDBOptions"
|
|
||||||
condition: qbs.targetOS.contains("osx")
|
|
||||||
files: [
|
|
||||||
"lldblib/lldboptionspage.cpp",
|
|
||||||
"lldblib/lldboptionspage.h",
|
|
||||||
"lldblib/lldboptionspagewidget.ui",
|
|
||||||
]
|
|
||||||
}
|
|
||||||
|
|
||||||
Properties {
|
Properties {
|
||||||
condition: qbs.targetOS.contains("windows")
|
condition: qbs.targetOS.contains("windows")
|
||||||
cpp.dynamicLibraries: [
|
cpp.dynamicLibraries: [
|
||||||
|
|||||||
@@ -190,14 +190,12 @@ enum DebuggerEngineType
|
|||||||
PdbEngineType = 0x008,
|
PdbEngineType = 0x008,
|
||||||
QmlEngineType = 0x020,
|
QmlEngineType = 0x020,
|
||||||
QmlCppEngineType = 0x040,
|
QmlCppEngineType = 0x040,
|
||||||
LldbLibEngineType = 0x080,
|
|
||||||
LldbEngineType = 0x100,
|
LldbEngineType = 0x100,
|
||||||
AllEngineTypes = GdbEngineType
|
AllEngineTypes = GdbEngineType
|
||||||
| CdbEngineType
|
| CdbEngineType
|
||||||
| PdbEngineType
|
| PdbEngineType
|
||||||
| QmlEngineType
|
| QmlEngineType
|
||||||
| QmlCppEngineType
|
| QmlCppEngineType
|
||||||
| LldbLibEngineType
|
|
||||||
| LldbEngineType
|
| LldbEngineType
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -75,7 +75,6 @@ DebuggerEngine *createGdbEngine(const DebuggerStartParameters &sp);
|
|||||||
DebuggerEngine *createPdbEngine(const DebuggerStartParameters &sp);
|
DebuggerEngine *createPdbEngine(const DebuggerStartParameters &sp);
|
||||||
DebuggerEngine *createQmlEngine(const DebuggerStartParameters &sp);
|
DebuggerEngine *createQmlEngine(const DebuggerStartParameters &sp);
|
||||||
DebuggerEngine *createQmlCppEngine(const DebuggerStartParameters &sp, QString *error);
|
DebuggerEngine *createQmlCppEngine(const DebuggerStartParameters &sp, QString *error);
|
||||||
DebuggerEngine *createLldbLibEngine(const DebuggerStartParameters &sp);
|
|
||||||
DebuggerEngine *createLldbEngine(const DebuggerStartParameters &sp);
|
DebuggerEngine *createLldbEngine(const DebuggerStartParameters &sp);
|
||||||
|
|
||||||
static const char *engineTypeName(DebuggerEngineType et)
|
static const char *engineTypeName(DebuggerEngineType et)
|
||||||
@@ -93,8 +92,6 @@ static const char *engineTypeName(DebuggerEngineType et)
|
|||||||
return "QML engine";
|
return "QML engine";
|
||||||
case Debugger::QmlCppEngineType:
|
case Debugger::QmlCppEngineType:
|
||||||
return "QML C++ engine";
|
return "QML C++ engine";
|
||||||
case Debugger::LldbLibEngineType:
|
|
||||||
return "LLDB binary engine";
|
|
||||||
case Debugger::LldbEngineType:
|
case Debugger::LldbEngineType:
|
||||||
return "LLDB command line engine";
|
return "LLDB command line engine";
|
||||||
case Debugger::AllEngineTypes:
|
case Debugger::AllEngineTypes:
|
||||||
@@ -518,8 +515,6 @@ DebuggerEngine *DebuggerRunControlFactory::createEngine(DebuggerEngineType et,
|
|||||||
return createQmlEngine(sp);
|
return createQmlEngine(sp);
|
||||||
case LldbEngineType:
|
case LldbEngineType:
|
||||||
return createLldbEngine(sp);
|
return createLldbEngine(sp);
|
||||||
case LldbLibEngineType:
|
|
||||||
return createLldbLibEngine(sp);
|
|
||||||
case QmlCppEngineType:
|
case QmlCppEngineType:
|
||||||
return createQmlCppEngine(sp, errorMessage);
|
return createQmlCppEngine(sp, errorMessage);
|
||||||
default:
|
default:
|
||||||
|
|||||||
@@ -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
|
|
||||||
@@ -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 <utils/qtcassert.h>
|
|
||||||
#include <QDebug>
|
|
||||||
#include <QProcess>
|
|
||||||
#include <QFileInfo>
|
|
||||||
#include <QThread>
|
|
||||||
#include <QMutexLocker>
|
|
||||||
|
|
||||||
#include <lldb/API/LLDB.h>
|
|
||||||
|
|
||||||
#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 *>("lldb::SBListener *");
|
|
||||||
qRegisterMetaType<lldb::SBEvent *>("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<WatchData> 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<WatchData> 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<WatchData> &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 "<<fr.GetFrameID();
|
|
||||||
qDebug() << "\t\tPC: " << ("0x" + QByteArray::number(
|
|
||||||
fr.GetPCAddress().GetLoadAddress(*m_target), 16)).data();
|
|
||||||
qDebug() << "\t\tFP: " << ("0x" + QByteArray::number(fr.GetFP(), 16)).data();
|
|
||||||
qDebug() << "\t\tSP: " << ("0x" + QByteArray::number(fr.GetSP(), 16)).data();
|
|
||||||
qDebug() << "\t\tsymbol: " << sym.IsValid() << sym.GetName() << sym.GetMangledName();
|
|
||||||
qDebug() << "\t\tfunction:" << func.IsValid();
|
|
||||||
qDebug() << "\t\ttu: " << tu.IsValid();
|
|
||||||
if (tu.IsValid())
|
|
||||||
|
|
||||||
qDebug() << "\t\tmodule: " << module.IsValid() << module.GetFileSpec().IsValid()
|
|
||||||
<< module.GetFileSpec().GetFilename();
|
|
||||||
qDebug() << "\t\tblock: " << block.IsValid() << block.GetInlinedName();
|
|
||||||
qDebug() << "\t\tfblock: " << block.IsValid() << block.GetInlinedName();
|
|
||||||
qDebug() << "\t\tle: " << le.IsValid() << le.GetLine()<<le.GetColumn();
|
|
||||||
qDebug() << "\t\tvalues: "<<values.IsValid() << values.GetSize();
|
|
||||||
qDebug() << "\t\tcontext: " << context.IsValid();
|
|
||||||
qDebug() << "\t\t\tmodule: " << context.GetModule().IsValid();
|
|
||||||
qDebug() << "\t\t\tfunction: " << context.GetFunction().IsValid();
|
|
||||||
qDebug() << "\t\t\tblock: " << context.GetBlock().IsValid();
|
|
||||||
qDebug() << "\t\t\tle: " << context.GetLineEntry().IsValid();
|
|
||||||
qDebug() << "\t\t\tsymbol: " << context.GetSymbol().IsValid();
|
|
||||||
// qDebug() << "\t\tdisassemly -->\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
|
|
||||||
@@ -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 <QQueue>
|
|
||||||
#include <QVariant>
|
|
||||||
#include <QThread>
|
|
||||||
#include <QStringList>
|
|
||||||
|
|
||||||
#include <lldb/API/LLDB.h>
|
|
||||||
|
|
||||||
#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<QByteArray> m_arguments;
|
|
||||||
QList<QByteArray> 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<QString, lldb::SBValue> m_localesCache;
|
|
||||||
QHash<BreakpointModelId, lldb::SBBreakpoint> m_breakpoints;
|
|
||||||
QHash<qint64, QString> m_frame_to_file;
|
|
||||||
|
|
||||||
void updateThreads();
|
|
||||||
void getWatchDataR(lldb::SBValue v, int level,
|
|
||||||
const QByteArray &p_iname, QList<WatchData> &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
|
|
||||||
@@ -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 <QLocalSocket>
|
|
||||||
#include <QCoreApplication>
|
|
||||||
#include <QSocketNotifier>
|
|
||||||
#include <QQueue>
|
|
||||||
|
|
||||||
#include <cstdio>
|
|
||||||
|
|
||||||
// #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<QByteArray> 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"
|
|
||||||
@@ -1,21 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
|
||||||
<plist version="1.0">
|
|
||||||
<dict>
|
|
||||||
<key>CFBundleDevelopmentRegion</key>
|
|
||||||
<string>English</string>
|
|
||||||
<key>CFBundleIdentifier</key>
|
|
||||||
<string>org.qt-project.qtcreator-lldb</string>
|
|
||||||
<key>CFBundleInfoDictionaryVersion</key>
|
|
||||||
<string>6.0</string>
|
|
||||||
<key>CFBundleName</key>
|
|
||||||
<string>Qt Creator LLDB Guest</string>
|
|
||||||
<key>CFBundleVersion</key>
|
|
||||||
<string>1.0</string>
|
|
||||||
<key>SecTaskAccess</key>
|
|
||||||
<array>
|
|
||||||
<string>allowed</string>
|
|
||||||
<string>safe</string>
|
|
||||||
</array>
|
|
||||||
</dict>
|
|
||||||
</plist>
|
|
||||||
@@ -1,2 +0,0 @@
|
|||||||
WITH_LLDB = $$(WITH_LLDB)
|
|
||||||
macx: !isEmpty(WITH_LLDB) : SUBDIRS += $$PWD/qtcreator-lldb.pro
|
|
||||||
@@ -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 += . .. ../.. ../../..
|
|
||||||
INCLUDEPATH += . .. ../.. ../../..
|
|
||||||
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
|
|
||||||
|
|
||||||
|
|
||||||
@@ -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 <utils/qtcassert.h>
|
|
||||||
|
|
||||||
#include <QLocalSocket>
|
|
||||||
|
|
||||||
#include <QSysInfo>
|
|
||||||
#include <QDebug>
|
|
||||||
#include <QFileInfo>
|
|
||||||
#include <QTimer>
|
|
||||||
|
|
||||||
#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<QLocalSocket *>(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<WatchData> &wd)
|
|
||||||
{
|
|
||||||
QByteArray p;
|
|
||||||
{
|
|
||||||
QDataStream s(&p, QIODevice::WriteOnly);
|
|
||||||
SET_NATIVE_BYTE_ORDER(s);
|
|
||||||
s << fullCycle;
|
|
||||||
s << quint64(wd.count());
|
|
||||||
for (int i = 0; i < wd.count(); ++i)
|
|
||||||
s << wd.at(i);
|
|
||||||
}
|
|
||||||
rpcCall(UpdateWatchData, p);
|
|
||||||
}
|
|
||||||
|
|
||||||
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
|
|
||||||
|
|
||||||
|
|
||||||
@@ -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 IPCENGINEGUEST_H
|
|
||||||
#define IPCENGINEGUEST_H
|
|
||||||
|
|
||||||
#include <debugger/breakhandler.h>
|
|
||||||
#include <debugger/debuggerengine.h>
|
|
||||||
#include <debugger/disassemblerlines.h>
|
|
||||||
#include <debugger/stackhandler.h>
|
|
||||||
#include <debugger/threadshandler.h>
|
|
||||||
|
|
||||||
#include <QQueue>
|
|
||||||
#include <QThread>
|
|
||||||
#include <QVariant>
|
|
||||||
|
|
||||||
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<WatchData> &);
|
|
||||||
|
|
||||||
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 // IPCENGINEGUEST_H
|
|
||||||
@@ -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 <debugger/debuggerstartparameters.h>
|
|
||||||
#include <debugger/breakhandler.h>
|
|
||||||
#include <debugger/breakpoint.h>
|
|
||||||
#include <debugger/disassemblerlines.h>
|
|
||||||
#include <debugger/moduleshandler.h>
|
|
||||||
#include <debugger/registerhandler.h>
|
|
||||||
#include <debugger/stackhandler.h>
|
|
||||||
#include <debugger/watchhandler.h>
|
|
||||||
#include <debugger/watchutils.h>
|
|
||||||
#include <debugger/threadshandler.h>
|
|
||||||
#include <debugger/disassembleragent.h>
|
|
||||||
#include <debugger/memoryagent.h>
|
|
||||||
#include <debugger/debuggerstreamops.h>
|
|
||||||
#include <debugger/debuggercore.h>
|
|
||||||
|
|
||||||
#include <utils/qtcassert.h>
|
|
||||||
|
|
||||||
#include <QSysInfo>
|
|
||||||
#include <QDebug>
|
|
||||||
#include <QFileInfo>
|
|
||||||
#include <QTimer>
|
|
||||||
#include <QLocalSocket>
|
|
||||||
|
|
||||||
#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<WatchData> wd;
|
|
||||||
s >> fullCycle;
|
|
||||||
s >> count;
|
|
||||||
for (qint64 i = 0; i < count; ++i) {
|
|
||||||
WatchData d;
|
|
||||||
s >> d;
|
|
||||||
wd.append(d);
|
|
||||||
}
|
|
||||||
WatchHandler *wh = watchHandler();
|
|
||||||
if (!wh)
|
|
||||||
break;
|
|
||||||
wh->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<QLocalSocket *>(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
|
|
||||||
|
|
||||||
|
|
||||||
@@ -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 <debugger/debuggerengine.h>
|
|
||||||
#include <debugger/threadshandler.h>
|
|
||||||
#include <debugger/stackhandler.h>
|
|
||||||
#include <debugger/breakhandler.h>
|
|
||||||
#include <debugger/sourceagent.h>
|
|
||||||
|
|
||||||
#include <QQueue>
|
|
||||||
#include <QVariant>
|
|
||||||
#include <QThread>
|
|
||||||
|
|
||||||
namespace Debugger {
|
|
||||||
namespace Internal {
|
|
||||||
|
|
||||||
class IPCEngineGuest;
|
|
||||||
class IPCEngineHost : public DebuggerEngine
|
|
||||||
{
|
|
||||||
Q_OBJECT
|
|
||||||
|
|
||||||
public:
|
|
||||||
explicit IPCEngineHost(const DebuggerStartParameters &startParameters);
|
|
||||||
~IPCEngineHost();
|
|
||||||
|
|
||||||
// use either one
|
|
||||||
void setLocalGuest(IPCEngineGuest *);
|
|
||||||
void setGuestDevice(QIODevice *);
|
|
||||||
|
|
||||||
enum Function
|
|
||||||
{
|
|
||||||
SetupIPC = 1,
|
|
||||||
StateChanged = 2,
|
|
||||||
SetupEngine = 3,
|
|
||||||
SetupInferior = 4,
|
|
||||||
RunEngine = 5,
|
|
||||||
ShutdownInferior = 6,
|
|
||||||
ShutdownEngine = 7,
|
|
||||||
DetachDebugger = 8,
|
|
||||||
ExecuteStep = 9,
|
|
||||||
ExecuteStepOut = 10,
|
|
||||||
ExecuteNext = 11,
|
|
||||||
ExecuteStepI = 12,
|
|
||||||
ExecuteNextI = 13,
|
|
||||||
ContinueInferior = 14,
|
|
||||||
InterruptInferior = 15,
|
|
||||||
ExecuteRunToLine = 16,
|
|
||||||
ExecuteRunToFunction = 17,
|
|
||||||
ExecuteJumpToLine = 18,
|
|
||||||
ActivateFrame = 19,
|
|
||||||
SelectThread = 20,
|
|
||||||
Disassemble = 21,
|
|
||||||
AddBreakpoint = 22,
|
|
||||||
RemoveBreakpoint = 23,
|
|
||||||
ChangeBreakpoint = 24,
|
|
||||||
RequestUpdateWatchData = 25,
|
|
||||||
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<quint64, DisassemblerAgent *> m_frameToDisassemblerAgent;
|
|
||||||
QHash<QString, SourceAgent *> m_sourceAgents;
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace Internal
|
|
||||||
} // namespace Debugger
|
|
||||||
|
|
||||||
#endif // DEBUGGER_LLDBENGINE_H
|
|
||||||
@@ -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 <debugger/debuggerstartparameters.h>
|
|
||||||
#include <debugger/debuggeractions.h>
|
|
||||||
#include <debugger/debuggerconstants.h>
|
|
||||||
#include <debugger/debuggerdialogs.h>
|
|
||||||
#include <debugger/debuggerplugin.h>
|
|
||||||
#include <debugger/debuggerstringutils.h>
|
|
||||||
|
|
||||||
#include <debugger/breakhandler.h>
|
|
||||||
#include <debugger/breakpoint.h>
|
|
||||||
#include <debugger/moduleshandler.h>
|
|
||||||
#include <debugger/registerhandler.h>
|
|
||||||
#include <debugger/stackhandler.h>
|
|
||||||
#include <debugger/watchhandler.h>
|
|
||||||
#include <debugger/watchutils.h>
|
|
||||||
#include <debugger/threadshandler.h>
|
|
||||||
#include <debugger/disassembleragent.h>
|
|
||||||
#include <debugger/memoryagent.h>
|
|
||||||
|
|
||||||
#include <coreplugin/icore.h>
|
|
||||||
#include <utils/qtcassert.h>
|
|
||||||
|
|
||||||
#include <QDebug>
|
|
||||||
#include <QProcess>
|
|
||||||
#include <QFileInfo>
|
|
||||||
#include <QThread>
|
|
||||||
#include <QCoreApplication>
|
|
||||||
|
|
||||||
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 *createLldbLibEngine(const DebuggerStartParameters &startParameters)
|
|
||||||
{
|
|
||||||
return new LldbEngineHost(startParameters);
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace Internal
|
|
||||||
} // namespace Debugger
|
|
||||||
|
|
||||||
@@ -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 <ssh/ssherrors.h>
|
|
||||||
#include <ssh/sshconnection.h>
|
|
||||||
#include <ssh/sshremoteprocess.h>
|
|
||||||
#include <ssh/sshremoteprocessrunner.h>
|
|
||||||
|
|
||||||
#include <QProcess>
|
|
||||||
#include <QQueue>
|
|
||||||
|
|
||||||
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<QByteArray> 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
|
|
||||||
@@ -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
|
|
||||||
}
|
|
||||||
@@ -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 <debugger/debuggerconstants.h>
|
|
||||||
#include <debugger/debuggerinternalconstants.h>
|
|
||||||
|
|
||||||
#include <coreplugin/icore.h>
|
|
||||||
|
|
||||||
#include <QCoreApplication>
|
|
||||||
#include <QUrl>
|
|
||||||
#include <QTextStream>
|
|
||||||
#include <QMessageBox>
|
|
||||||
#include <QDesktopServices>
|
|
||||||
|
|
||||||
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("F.Lldb");
|
|
||||||
setDisplayName(tr("LLDB"));
|
|
||||||
setCategory(Debugger::Constants::DEBUGGER_SETTINGS_CATEGORY);
|
|
||||||
setDisplayCategory(QCoreApplication::translate("Debugger", Constants::DEBUGGER_SETTINGS_TR_CATEGORY));
|
|
||||||
setCategoryIcon(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(QLatin1String("lldb"));
|
|
||||||
}
|
|
||||||
|
|
||||||
void addLldbOptionPages(QList<Core::IOptionsPage *> *opts)
|
|
||||||
{
|
|
||||||
opts->push_back(new LldbOptionsPage);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
} // namespace Internal
|
|
||||||
} // namespace Debugger
|
|
||||||
@@ -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 LLDBOPTIONSPAGE_H
|
|
||||||
#define LLDBOPTIONSPAGE_H
|
|
||||||
|
|
||||||
#include <coreplugin/dialogs/ioptionspage.h>
|
|
||||||
#include "ui_lldboptionspagewidget.h"
|
|
||||||
|
|
||||||
#include <QWidget>
|
|
||||||
#include <QPointer>
|
|
||||||
#include <QSharedPointer>
|
|
||||||
#include <QSettings>
|
|
||||||
|
|
||||||
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<LldbOptionsPageWidget> m_widget;
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace Internal
|
|
||||||
} // namespace Debugger
|
|
||||||
|
|
||||||
#endif // LLDBOPTIONSPAGE_H
|
|
||||||
@@ -1,59 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<ui version="4.0">
|
|
||||||
<class>Debugger::Internal::LldbOptionsPageWidget</class>
|
|
||||||
<widget class="QWidget" name="Debugger::Internal::LldbOptionsPageWidget">
|
|
||||||
<property name="geometry">
|
|
||||||
<rect>
|
|
||||||
<x>0</x>
|
|
||||||
<y>0</y>
|
|
||||||
<width>522</width>
|
|
||||||
<height>512</height>
|
|
||||||
</rect>
|
|
||||||
</property>
|
|
||||||
<layout class="QVBoxLayout" name="verticalLayout">
|
|
||||||
<item>
|
|
||||||
<layout class="QHBoxLayout" name="horizontalLayout"/>
|
|
||||||
</item>
|
|
||||||
<item>
|
|
||||||
<widget class="QGroupBox" name="enableLldb">
|
|
||||||
<property name="title">
|
|
||||||
<string>Enable LLDB</string>
|
|
||||||
</property>
|
|
||||||
<property name="checkable">
|
|
||||||
<bool>true</bool>
|
|
||||||
</property>
|
|
||||||
<property name="checked">
|
|
||||||
<bool>false</bool>
|
|
||||||
</property>
|
|
||||||
<layout class="QVBoxLayout" name="verticalLayout_2">
|
|
||||||
<item>
|
|
||||||
<widget class="QCheckBox" name="gdbEmu">
|
|
||||||
<property name="text">
|
|
||||||
<string>Use GDB Python dumpers</string>
|
|
||||||
</property>
|
|
||||||
<property name="checked">
|
|
||||||
<bool>false</bool>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
</layout>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item>
|
|
||||||
<spacer name="verticalSpacer">
|
|
||||||
<property name="orientation">
|
|
||||||
<enum>Qt::Vertical</enum>
|
|
||||||
</property>
|
|
||||||
<property name="sizeHint" stdset="0">
|
|
||||||
<size>
|
|
||||||
<width>20</width>
|
|
||||||
<height>203</height>
|
|
||||||
</size>
|
|
||||||
</property>
|
|
||||||
</spacer>
|
|
||||||
</item>
|
|
||||||
</layout>
|
|
||||||
</widget>
|
|
||||||
<resources/>
|
|
||||||
<connections/>
|
|
||||||
</ui>
|
|
||||||
@@ -87,5 +87,3 @@ SUBDIRS += debugger/dumper.pro
|
|||||||
linux-* {
|
linux-* {
|
||||||
SUBDIRS += debugger/ptracepreload.pro
|
SUBDIRS += debugger/ptracepreload.pro
|
||||||
}
|
}
|
||||||
|
|
||||||
include (debugger/lldblib/guest/qtcreator-lldb.pri)
|
|
||||||
|
|||||||
Reference in New Issue
Block a user