forked from qt-creator/qt-creator
debugger: Replace adapter classes by GdbEngine subclasses
Change-Id: Iee6195b1eed5251545b9d688221ac2edf19325c1 Reviewed-by: Christian Kandeler <christian.kandeler@nokia.com>
This commit is contained in:
@@ -166,8 +166,6 @@ QtcPlugin {
|
||||
"cdb/cdbparsehelpers.cpp",
|
||||
"cdb/cdbparsehelpers.h",
|
||||
"gdb/gdb.qrc",
|
||||
"gdb/abstractgdbadapter.cpp",
|
||||
"gdb/abstractgdbadapter.h",
|
||||
"gdb/abstractgdbprocess.cpp",
|
||||
"gdb/abstractgdbprocess.h",
|
||||
"gdb/abstractplaingdbadapter.cpp",
|
||||
|
||||
@@ -1357,6 +1357,7 @@ bool DebuggerPluginPrivate::parseArgument(QStringList::const_iterator &it,
|
||||
sp.remoteArchitecture = val;
|
||||
else if (key == QLatin1String("core")) {
|
||||
sp.startMode = AttachCore;
|
||||
sp.closeMode = DetachAtClose;
|
||||
sp.coreFile = val;
|
||||
sp.displayName = tr("Core file \"%1\"").arg(sp.coreFile);
|
||||
sp.startMessage = tr("Attaching to core file %1.").arg(sp.coreFile);
|
||||
@@ -1590,6 +1591,7 @@ void DebuggerPluginPrivate::attachCore()
|
||||
sp.coreFile = dlg.coreFile();
|
||||
sp.displayName = tr("Core file \"%1\"").arg(dlg.coreFile());
|
||||
sp.startMode = AttachCore;
|
||||
sp.closeMode = DetachAtClose;
|
||||
sp.debuggerCommand = dlg.debuggerCommand();
|
||||
sp.toolChainAbi = dlg.abi();
|
||||
sp.sysroot = dlg.sysroot();
|
||||
@@ -1701,6 +1703,7 @@ void DebuggerPluginPrivate::loadRemoteCoreFile()
|
||||
return;
|
||||
sp.displayName = tr("Core file \"%1\"").arg(sp.coreFile);
|
||||
sp.startMode = AttachCore;
|
||||
sp.closeMode = DetachAtClose;
|
||||
//sp.debuggerCommand = dlg.debuggerCommand();
|
||||
//sp.toolChainAbi = dlg.abi();
|
||||
sp.sysroot = dlg.sysroot();
|
||||
|
||||
@@ -1,179 +0,0 @@
|
||||
/**************************************************************************
|
||||
**
|
||||
** This file is part of Qt Creator
|
||||
**
|
||||
** Copyright (c) 2012 Nokia Corporation and/or its subsidiary(-ies).
|
||||
**
|
||||
** Contact: Nokia Corporation (qt-info@nokia.com)
|
||||
**
|
||||
**
|
||||
** GNU Lesser General Public License Usage
|
||||
**
|
||||
** 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, Nokia gives you certain additional
|
||||
** rights. These rights are described in the Nokia Qt LGPL Exception
|
||||
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
|
||||
**
|
||||
** Other Usage
|
||||
**
|
||||
** Alternatively, this file may be used in accordance with the terms and
|
||||
** conditions contained in a signed written agreement between you and Nokia.
|
||||
**
|
||||
** If you have questions regarding the use of this file, please contact
|
||||
** Nokia at qt-info@nokia.com.
|
||||
**
|
||||
**************************************************************************/
|
||||
|
||||
#include "abstractgdbadapter.h"
|
||||
#include "gdbengine.h"
|
||||
#include "debuggerstartparameters.h"
|
||||
#include "abstractgdbprocess.h"
|
||||
#include "procinterrupt.h"
|
||||
|
||||
#include <utils/qtcassert.h>
|
||||
#include <utils/qtcprocess.h>
|
||||
|
||||
#include <QProcess>
|
||||
|
||||
namespace Debugger {
|
||||
namespace Internal {
|
||||
|
||||
AbstractGdbAdapter::AbstractGdbAdapter(GdbEngine *engine)
|
||||
: m_engine(engine)
|
||||
{
|
||||
}
|
||||
|
||||
AbstractGdbAdapter::~AbstractGdbAdapter()
|
||||
{
|
||||
disconnect();
|
||||
}
|
||||
|
||||
//void AbstractGdbAdapter::shutdown()
|
||||
//{
|
||||
//}
|
||||
|
||||
//void AbstractGdbAdapter::runEngine()
|
||||
//{
|
||||
// QTC_ASSERT(state() == EngineRunRequested, qDebug() << state());
|
||||
//}
|
||||
|
||||
/*
|
||||
const char *AbstractGdbAdapter::inferiorShutdownCommand() const
|
||||
{
|
||||
return "kill";
|
||||
}
|
||||
*/
|
||||
|
||||
void AbstractGdbAdapter::write(const QByteArray &data)
|
||||
{
|
||||
gdbProc()->write(data);
|
||||
}
|
||||
|
||||
bool AbstractGdbAdapter::isCodaAdapter() const
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
bool AbstractGdbAdapter::prepareCommand()
|
||||
{
|
||||
#ifdef Q_OS_WIN
|
||||
Utils::QtcProcess::SplitError perr;
|
||||
startParameters().processArgs = Utils::QtcProcess::prepareArgs(
|
||||
startParameters().processArgs, &perr,
|
||||
&startParameters().environment, &startParameters().workingDirectory);
|
||||
if (perr != Utils::QtcProcess::SplitOk) {
|
||||
// perr == BadQuoting is never returned on Windows
|
||||
// FIXME? QTCREATORBUG-2809
|
||||
m_engine->handleAdapterStartFailed(QCoreApplication::translate("DebuggerEngine", // Same message in CdbEngine
|
||||
"Debugging complex command lines is currently not supported on Windows."), QString());
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
|
||||
QString AbstractGdbAdapter::msgGdbStopFailed(const QString &why)
|
||||
{
|
||||
return tr("The gdb process could not be stopped:\n%1").arg(why);
|
||||
}
|
||||
|
||||
QString AbstractGdbAdapter::msgInferiorStopFailed(const QString &why)
|
||||
{
|
||||
return tr("Application process could not be stopped:\n%1").arg(why);
|
||||
}
|
||||
|
||||
QString AbstractGdbAdapter::msgInferiorSetupOk()
|
||||
{
|
||||
return tr("Application started");
|
||||
}
|
||||
|
||||
QString AbstractGdbAdapter::msgInferiorRunOk()
|
||||
{
|
||||
return tr("Application running");
|
||||
}
|
||||
|
||||
QString AbstractGdbAdapter::msgAttachedToStoppedInferior()
|
||||
{
|
||||
return tr("Attached to stopped application");
|
||||
}
|
||||
|
||||
QString AbstractGdbAdapter::msgConnectRemoteServerFailed(const QString &why)
|
||||
{
|
||||
return tr("Connecting to remote server failed:\n%1").arg(why);
|
||||
}
|
||||
|
||||
DebuggerState AbstractGdbAdapter::state() const
|
||||
{
|
||||
return m_engine->state();
|
||||
}
|
||||
|
||||
const DebuggerStartParameters &AbstractGdbAdapter::startParameters() const
|
||||
{
|
||||
return m_engine->startParameters();
|
||||
}
|
||||
|
||||
DebuggerStartParameters &AbstractGdbAdapter::startParameters()
|
||||
{
|
||||
return m_engine->startParameters();
|
||||
}
|
||||
|
||||
void AbstractGdbAdapter::showMessage(const QString &msg, int channel, int timeout)
|
||||
{
|
||||
m_engine->showMessage(msg, channel, timeout);
|
||||
}
|
||||
|
||||
void AbstractGdbAdapter::handleRemoteSetupDone(int gdbServerPort, int qmlPort)
|
||||
{
|
||||
Q_UNUSED(gdbServerPort);
|
||||
Q_UNUSED(qmlPort);
|
||||
}
|
||||
|
||||
void AbstractGdbAdapter::handleRemoteSetupFailed(const QString &reason)
|
||||
{
|
||||
Q_UNUSED(reason);
|
||||
}
|
||||
|
||||
void AbstractGdbAdapter::interruptLocalInferior(qint64 pid)
|
||||
{
|
||||
QTC_ASSERT(state() == InferiorStopRequested, qDebug() << state(); return);
|
||||
if (pid <= 0) {
|
||||
showMessage(QLatin1String("TRYING TO INTERRUPT INFERIOR BEFORE PID WAS OBTAINED"), LogError);
|
||||
return;
|
||||
}
|
||||
QString errorMessage;
|
||||
if (interruptProcess(pid, GdbEngineType, &errorMessage)) {
|
||||
showMessage(QLatin1String("Interrupted ") + QString::number(pid));
|
||||
} else {
|
||||
showMessage(errorMessage, LogError);
|
||||
m_engine->notifyInferiorStopFailed();
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace Internal
|
||||
} // namespace Debugger
|
||||
@@ -1,116 +0,0 @@
|
||||
/**************************************************************************
|
||||
**
|
||||
** This file is part of Qt Creator
|
||||
**
|
||||
** Copyright (c) 2012 Nokia Corporation and/or its subsidiary(-ies).
|
||||
**
|
||||
** Contact: Nokia Corporation (qt-info@nokia.com)
|
||||
**
|
||||
**
|
||||
** GNU Lesser General Public License Usage
|
||||
**
|
||||
** 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, Nokia gives you certain additional
|
||||
** rights. These rights are described in the Nokia Qt LGPL Exception
|
||||
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
|
||||
**
|
||||
** Other Usage
|
||||
**
|
||||
** Alternatively, this file may be used in accordance with the terms and
|
||||
** conditions contained in a signed written agreement between you and Nokia.
|
||||
**
|
||||
** If you have questions regarding the use of this file, please contact
|
||||
** Nokia at qt-info@nokia.com.
|
||||
**
|
||||
**************************************************************************/
|
||||
|
||||
#ifndef DEBUGGER_ABSTRACT_GDB_ADAPTER
|
||||
#define DEBUGGER_ABSTRACT_GDB_ADAPTER
|
||||
|
||||
#include "debuggerconstants.h"
|
||||
// Need to include gdbengine.h as otherwise MSVC crashes
|
||||
// on invoking the first adapter callback in a *derived* adapter class.
|
||||
#include "gdbengine.h"
|
||||
|
||||
#include <QObject>
|
||||
|
||||
namespace Debugger {
|
||||
class DebuggerStartParameters;
|
||||
|
||||
namespace Internal {
|
||||
|
||||
class AbstractGdbProcess;
|
||||
class GdbResponse;
|
||||
|
||||
// AbstractGdbAdapter is inherited by PlainGdbAdapter used for local
|
||||
// debugging and CodaGdbAdapter used for on-device debugging.
|
||||
// In the PlainGdbAdapter case it's just a wrapper around a QProcess running
|
||||
// gdb, in the CodaGdbAdapter case it's the interface to the gdb process in
|
||||
// the whole rfcomm/gdb/gdbserver combo.
|
||||
class AbstractGdbAdapter : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
enum DumperHandling
|
||||
{
|
||||
DumperNotAvailable,
|
||||
DumperLoadedByAdapter,
|
||||
DumperLoadedByGdbPreload,
|
||||
DumperLoadedByGdb
|
||||
};
|
||||
|
||||
explicit AbstractGdbAdapter(GdbEngine *engine);
|
||||
virtual ~AbstractGdbAdapter();
|
||||
|
||||
virtual void write(const QByteArray &data);
|
||||
|
||||
virtual void startAdapter() = 0;
|
||||
virtual void handleGdbStartDone() = 0;
|
||||
virtual void handleGdbStartFailed() = 0;
|
||||
virtual void setupInferior() = 0;
|
||||
virtual void runEngine() = 0;
|
||||
virtual void interruptInferior() = 0;
|
||||
virtual void shutdownAdapter() = 0;
|
||||
virtual AbstractGdbProcess *gdbProc() = 0;
|
||||
|
||||
virtual DumperHandling dumperHandling() const = 0;
|
||||
|
||||
static QString msgGdbStopFailed(const QString &why);
|
||||
static QString msgInferiorStopFailed(const QString &why);
|
||||
static QString msgAttachedToStoppedInferior();
|
||||
static QString msgInferiorSetupOk();
|
||||
static QString msgInferiorRunOk();
|
||||
static QString msgConnectRemoteServerFailed(const QString &why);
|
||||
|
||||
// CODA specific stuff
|
||||
virtual bool isCodaAdapter() const;
|
||||
virtual void codaReloadRegisters() {}
|
||||
virtual void codaReloadThreads() {}
|
||||
|
||||
virtual void handleRemoteSetupDone(int gdbServerPort, int qmlPort);
|
||||
virtual void handleRemoteSetupFailed(const QString &reason);
|
||||
|
||||
|
||||
protected:
|
||||
DebuggerState state() const;
|
||||
GdbEngine *engine() const { return m_engine; }
|
||||
const DebuggerStartParameters &startParameters() const;
|
||||
DebuggerStartParameters &startParameters();
|
||||
void showMessage(const QString &msg, int channel = LogDebug, int timeout = 1);
|
||||
bool prepareCommand();
|
||||
void interruptLocalInferior(qint64 pid);
|
||||
|
||||
GdbEngine * const m_engine;
|
||||
};
|
||||
|
||||
} // namespace Internal
|
||||
} // namespace Debugger
|
||||
|
||||
#endif // DEBUGGER_ABSTRACT_GDB_ADAPTER
|
||||
@@ -48,62 +48,62 @@ namespace Debugger {
|
||||
namespace Internal {
|
||||
|
||||
#define CB(callback) \
|
||||
static_cast<GdbEngine::AdapterCallback>(&AbstractPlainGdbAdapter::callback), \
|
||||
static_cast<GdbEngine::GdbCommandCallback>(&GdbAbstractPlainEngine::callback), \
|
||||
STRINGIFY(callback)
|
||||
|
||||
AbstractPlainGdbAdapter::AbstractPlainGdbAdapter(GdbEngine *engine)
|
||||
: AbstractGdbAdapter(engine)
|
||||
{
|
||||
}
|
||||
GdbAbstractPlainEngine::GdbAbstractPlainEngine(const DebuggerStartParameters &startParameters,
|
||||
DebuggerEngine *masterEngine)
|
||||
: GdbEngine(startParameters, masterEngine)
|
||||
{}
|
||||
|
||||
void AbstractPlainGdbAdapter::setupInferior()
|
||||
void GdbAbstractPlainEngine::setupInferior()
|
||||
{
|
||||
QTC_ASSERT(state() == InferiorSetupRequested, qDebug() << state());
|
||||
if (!startParameters().processArgs.isEmpty()) {
|
||||
QString args = startParameters().processArgs;
|
||||
m_engine->postCommand("-exec-arguments " + toLocalEncoding(args));
|
||||
postCommand("-exec-arguments " + toLocalEncoding(args));
|
||||
}
|
||||
m_engine->postCommand("-file-exec-and-symbols \"" + execFilePath() + '"',
|
||||
postCommand("-file-exec-and-symbols \"" + execFilePath() + '"',
|
||||
CB(handleFileExecAndSymbols));
|
||||
}
|
||||
|
||||
void AbstractPlainGdbAdapter::handleFileExecAndSymbols(const GdbResponse &response)
|
||||
void GdbAbstractPlainEngine::handleFileExecAndSymbols(const GdbResponse &response)
|
||||
{
|
||||
QTC_ASSERT(state() == InferiorSetupRequested, qDebug() << state());
|
||||
if (response.resultClass == GdbResultDone) {
|
||||
m_engine->handleInferiorPrepared();
|
||||
handleInferiorPrepared();
|
||||
} else {
|
||||
QByteArray ba = response.data.findChild("msg").data();
|
||||
QString msg = fromLocalEncoding(ba);
|
||||
// Extend the message a bit in unknown cases.
|
||||
if (!ba.endsWith("File format not recognized"))
|
||||
msg = tr("Starting executable failed:\n") + msg;
|
||||
m_engine->notifyInferiorSetupFailed(msg);
|
||||
notifyInferiorSetupFailed(msg);
|
||||
}
|
||||
}
|
||||
|
||||
void AbstractPlainGdbAdapter::runEngine()
|
||||
void GdbAbstractPlainEngine::runEngine()
|
||||
{
|
||||
m_engine->postCommand("-exec-run", GdbEngine::RunRequest, CB(handleExecRun));
|
||||
postCommand("-exec-run", GdbEngine::RunRequest, CB(handleExecRun));
|
||||
}
|
||||
|
||||
void AbstractPlainGdbAdapter::handleExecRun(const GdbResponse &response)
|
||||
void GdbAbstractPlainEngine::handleExecRun(const GdbResponse &response)
|
||||
{
|
||||
QTC_ASSERT(state() == EngineRunRequested, qDebug() << state());
|
||||
if (response.resultClass == GdbResultRunning) {
|
||||
m_engine->notifyEngineRunAndInferiorRunOk();
|
||||
notifyEngineRunAndInferiorRunOk();
|
||||
//showStatusMessage(tr("Running..."));
|
||||
showMessage(_("INFERIOR STARTED"));
|
||||
showMessage(msgInferiorSetupOk(), StatusBar);
|
||||
// FIXME: That's the wrong place for it.
|
||||
if (debuggerCore()->boolSetting(EnableReverseDebugging))
|
||||
m_engine->postCommand("target record");
|
||||
postCommand("target record");
|
||||
} else {
|
||||
QString msg = fromLocalEncoding(response.data.findChild("msg").data());
|
||||
//QTC_CHECK(status() == InferiorRunOk);
|
||||
//interruptInferior();
|
||||
showMessage(msg);
|
||||
m_engine->notifyEngineRunFailed();
|
||||
notifyEngineRunFailed();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -33,20 +33,21 @@
|
||||
#ifndef ABSTRACTPLAINGDBADAPTER_H
|
||||
#define ABSTRACTPLAINGDBADAPTER_H
|
||||
|
||||
#include "abstractgdbadapter.h"
|
||||
#include "gdbengine.h"
|
||||
|
||||
namespace Debugger {
|
||||
namespace Internal {
|
||||
|
||||
class AbstractPlainGdbAdapter : public AbstractGdbAdapter
|
||||
class GdbAbstractPlainEngine : public GdbEngine
|
||||
{
|
||||
// Needs tr - context
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit AbstractPlainGdbAdapter(GdbEngine *engine);
|
||||
GdbAbstractPlainEngine(const DebuggerStartParameters &startParameters,
|
||||
DebuggerEngine *masterEngine);
|
||||
|
||||
virtual void setupInferior();
|
||||
void setupInferior();
|
||||
void runEngine();
|
||||
|
||||
private:
|
||||
|
||||
@@ -45,7 +45,7 @@ namespace Debugger {
|
||||
namespace Internal {
|
||||
|
||||
#define CB(callback) \
|
||||
static_cast<GdbEngine::AdapterCallback>(&AttachGdbAdapter::callback), \
|
||||
static_cast<GdbEngine::GdbCommandCallback>(&GdbAttachEngine::callback), \
|
||||
STRINGIFY(callback)
|
||||
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
@@ -54,47 +54,37 @@ namespace Internal {
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
|
||||
AttachGdbAdapter::AttachGdbAdapter(GdbEngine *engine)
|
||||
: AbstractGdbAdapter(engine)
|
||||
GdbAttachEngine::GdbAttachEngine(const DebuggerStartParameters &startParameters,
|
||||
DebuggerEngine *masterEngine)
|
||||
: GdbEngine(startParameters, masterEngine)
|
||||
{
|
||||
}
|
||||
|
||||
void AttachGdbAdapter::startAdapter()
|
||||
void GdbAttachEngine::setupEngine()
|
||||
{
|
||||
QTC_ASSERT(state() == EngineSetupRequested, qDebug() << state());
|
||||
showMessage(_("TRYING TO START ADAPTER"));
|
||||
m_engine->startGdb();
|
||||
startGdb();
|
||||
}
|
||||
|
||||
void AttachGdbAdapter::handleGdbStartDone()
|
||||
{
|
||||
m_engine->handleAdapterStarted();
|
||||
}
|
||||
|
||||
void AttachGdbAdapter::handleGdbStartFailed()
|
||||
{
|
||||
}
|
||||
|
||||
void AttachGdbAdapter::setupInferior()
|
||||
void GdbAttachEngine::setupInferior()
|
||||
{
|
||||
QTC_ASSERT(state() == InferiorSetupRequested, qDebug() << state());
|
||||
const qint64 pid = startParameters().attachPID;
|
||||
m_engine->postCommand("attach " + QByteArray::number(pid), CB(handleAttach));
|
||||
postCommand("attach " + QByteArray::number(pid), CB(handleAttach));
|
||||
// Task 254674 does not want to remove them
|
||||
//qq->breakHandler()->removeAllBreakpoints();
|
||||
}
|
||||
|
||||
void AttachGdbAdapter::runEngine()
|
||||
void GdbAttachEngine::runEngine()
|
||||
{
|
||||
QTC_ASSERT(state() == EngineRunRequested, qDebug() << state());
|
||||
m_engine->showStatusMessage(tr("Attached to process %1.")
|
||||
.arg(m_engine->inferiorPid()));
|
||||
m_engine->notifyEngineRunAndInferiorStopOk();
|
||||
GdbMi data;
|
||||
m_engine->handleStop1(data);
|
||||
showStatusMessage(tr("Attached to process %1.").arg(inferiorPid()));
|
||||
notifyEngineRunAndInferiorStopOk();
|
||||
handleStop1(GdbMi());
|
||||
}
|
||||
|
||||
void AttachGdbAdapter::handleAttach(const GdbResponse &response)
|
||||
void GdbAttachEngine::handleAttach(const GdbResponse &response)
|
||||
{
|
||||
QTC_ASSERT(state() == InferiorSetupRequested, qDebug() << state());
|
||||
switch (response.resultClass) {
|
||||
@@ -102,28 +92,28 @@ void AttachGdbAdapter::handleAttach(const GdbResponse &response)
|
||||
case GdbResultRunning:
|
||||
showMessage(_("INFERIOR ATTACHED"));
|
||||
showMessage(msgAttachedToStoppedInferior(), StatusBar);
|
||||
m_engine->handleInferiorPrepared();
|
||||
handleInferiorPrepared();
|
||||
break;
|
||||
case GdbResultError:
|
||||
if (response.data.findChild("msg").data() == "ptrace: Operation not permitted.") {
|
||||
m_engine->notifyInferiorSetupFailed(DumperHelper::msgPtraceError(startParameters().startMode));
|
||||
notifyInferiorSetupFailed(DumperHelper::msgPtraceError(startParameters().startMode));
|
||||
break;
|
||||
}
|
||||
// if msg != "ptrace: ..." fall through
|
||||
default:
|
||||
QString msg = QString::fromLocal8Bit(response.data.findChild("msg").data());
|
||||
m_engine->notifyInferiorSetupFailed(msg);
|
||||
notifyInferiorSetupFailed(msg);
|
||||
}
|
||||
}
|
||||
|
||||
void AttachGdbAdapter::interruptInferior()
|
||||
void GdbAttachEngine::interruptInferior2()
|
||||
{
|
||||
interruptLocalInferior(startParameters().attachPID);
|
||||
}
|
||||
|
||||
void AttachGdbAdapter::shutdownAdapter()
|
||||
void GdbAttachEngine::shutdownEngine()
|
||||
{
|
||||
m_engine->notifyAdapterShutdownOk();
|
||||
notifyAdapterShutdownOk();
|
||||
}
|
||||
|
||||
} // namespace Internal
|
||||
|
||||
@@ -33,7 +33,7 @@
|
||||
#ifndef DEBUGGER_ATTACHGDBADAPTER_H
|
||||
#define DEBUGGER_ATTACHGDBADAPTER_H
|
||||
|
||||
#include "abstractgdbadapter.h"
|
||||
#include "gdbengine.h"
|
||||
#include "localgdbprocess.h"
|
||||
|
||||
namespace Debugger {
|
||||
@@ -45,23 +45,22 @@ namespace Internal {
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
|
||||
class AttachGdbAdapter : public AbstractGdbAdapter
|
||||
class GdbAttachEngine : public GdbEngine
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit AttachGdbAdapter(GdbEngine *engine);
|
||||
GdbAttachEngine(const DebuggerStartParameters &startParameters,
|
||||
DebuggerEngine *masterEngine);
|
||||
|
||||
private:
|
||||
DumperHandling dumperHandling() const { return DumperLoadedByGdb; }
|
||||
|
||||
void startAdapter();
|
||||
void handleGdbStartDone();
|
||||
void handleGdbStartFailed();
|
||||
void setupEngine();
|
||||
void setupInferior();
|
||||
void runEngine();
|
||||
void interruptInferior();
|
||||
void shutdownAdapter();
|
||||
void interruptInferior2();
|
||||
void shutdownEngine();
|
||||
|
||||
AbstractGdbProcess *gdbProc() { return &m_gdbProc; }
|
||||
void handleAttach(const GdbResponse &response);
|
||||
|
||||
@@ -34,7 +34,6 @@
|
||||
#include "gdbmi.h"
|
||||
|
||||
#include "debuggerstartparameters.h"
|
||||
#include "abstractgdbadapter.h"
|
||||
#include "debuggeractions.h"
|
||||
#include "debuggercore.h"
|
||||
#include "debuggerstringutils.h"
|
||||
@@ -1107,7 +1106,7 @@ void GdbEngine::tryLoadDebuggingHelpersClassic()
|
||||
return;
|
||||
|
||||
PRECONDITION;
|
||||
if (m_gdbAdapter->dumperHandling() == AbstractGdbAdapter::DumperNotAvailable) {
|
||||
if (dumperHandling() == GdbEngine::DumperNotAvailable) {
|
||||
// Load at least gdb macro based dumpers.
|
||||
m_debuggingHelperState = DebuggingHelperLoadTried;
|
||||
postCommand(Utils::FileReader::fetchQrc(_(":/gdb/gdbmacros.txt")));
|
||||
|
||||
@@ -65,7 +65,7 @@
|
||||
#endif
|
||||
|
||||
#define CB(callback) \
|
||||
static_cast<GdbEngine::AdapterCallback>(&CodaGdbAdapter::callback), \
|
||||
static_cast<GdbEngine::GdbCommandCallback>(&GdbCodaEngine::callback), \
|
||||
STRINGIFY(callback)
|
||||
|
||||
enum { debug = 0 };
|
||||
@@ -91,7 +91,7 @@ using namespace Coda;
|
||||
|
||||
static inline QString startMsg(const Coda::Session &session)
|
||||
{
|
||||
return CodaGdbAdapter::tr("Process started, PID: 0x%1, thread id: 0x%2, "
|
||||
return GdbCodaEngine::tr("Process started, PID: 0x%1, thread id: 0x%2, "
|
||||
"code segment: 0x%3, data segment: 0x%4.")
|
||||
.arg(session.pid, 0, 16).arg(session.tid, 0, 16)
|
||||
.arg(session.codeseg, 0, 16).arg(session.dataseg, 0, 16);
|
||||
@@ -118,8 +118,9 @@ static inline QString startMsg(const Coda::Session &session)
|
||||
* - Stop all threads once one stops?
|
||||
* - Breakpoints do not trigger in threads other than the main thread. */
|
||||
|
||||
CodaGdbAdapter::CodaGdbAdapter(GdbEngine *engine) :
|
||||
AbstractGdbAdapter(engine),
|
||||
GdbCodaEngine:: GdbCodaEngine(const DebuggerStartParameters &startParameters,
|
||||
DebuggerEngine *masterEngine)
|
||||
: GdbEngine(startParameters, masterEngine),
|
||||
m_running(false),
|
||||
m_stopReason(0),
|
||||
m_gdbAckMode(true),
|
||||
@@ -149,7 +150,7 @@ CodaGdbAdapter::CodaGdbAdapter(GdbEngine *engine) :
|
||||
this, SLOT(setVerbose(QVariant)));
|
||||
}
|
||||
|
||||
void CodaGdbAdapter::setupDeviceSignals()
|
||||
void GdbCodaEngine::setupDeviceSignals()
|
||||
{
|
||||
connect(m_codaDevice.data(), SIGNAL(error(QString)),
|
||||
this, SLOT(codaDeviceError(QString)));
|
||||
@@ -161,7 +162,7 @@ void CodaGdbAdapter::setupDeviceSignals()
|
||||
this, SLOT(codaDeviceRemoved(SymbianUtils::SymbianDevice)));
|
||||
}
|
||||
|
||||
CodaGdbAdapter::~CodaGdbAdapter()
|
||||
GdbCodaEngine::~GdbCodaEngine()
|
||||
{
|
||||
if (m_codaDevice)
|
||||
SymbianUtils::SymbianDeviceManager::instance()->releaseCodaDevice(m_codaDevice);
|
||||
@@ -170,12 +171,12 @@ CodaGdbAdapter::~CodaGdbAdapter()
|
||||
logMessage(QLatin1String("Shutting down.\n"));
|
||||
}
|
||||
|
||||
void CodaGdbAdapter::setVerbose(const QVariant &value)
|
||||
void GdbCodaEngine::setVerbose(const QVariant &value)
|
||||
{
|
||||
setVerbose(value.toInt());
|
||||
}
|
||||
|
||||
void CodaGdbAdapter::setVerbose(int verbose)
|
||||
void GdbCodaEngine::setVerbose(int verbose)
|
||||
{
|
||||
if (debug)
|
||||
qDebug("CodaGdbAdapter::setVerbose %d", verbose);
|
||||
@@ -184,12 +185,12 @@ void CodaGdbAdapter::setVerbose(int verbose)
|
||||
m_codaDevice->setVerbose(m_verbose);
|
||||
}
|
||||
|
||||
void CodaGdbAdapter::codaLogMessage(const QString &msg)
|
||||
void GdbCodaEngine::codaLogMessage(const QString &msg)
|
||||
{
|
||||
logMessage(_("CODA ") + msg);
|
||||
}
|
||||
|
||||
void CodaGdbAdapter::setGdbServerName(const QString &name)
|
||||
void GdbCodaEngine::setGdbServerName(const QString &name)
|
||||
{
|
||||
m_gdbServerName = name;
|
||||
}
|
||||
@@ -210,7 +211,7 @@ static QPair<QString, unsigned short> splitIpAddressSpec(const QString &addressS
|
||||
return QPair<QString, unsigned short>(address, port);
|
||||
}
|
||||
|
||||
void CodaGdbAdapter::handleCodaRunControlModuleLoadContextSuspendedEvent(const CodaRunControlModuleLoadContextSuspendedEvent &se)
|
||||
void GdbCodaEngine::handleCodaRunControlModuleLoadContextSuspendedEvent(const CodaRunControlModuleLoadContextSuspendedEvent &se)
|
||||
{
|
||||
m_snapshot.resetMemory();
|
||||
const ModuleLoadEventInfo &minfo = se.info();
|
||||
@@ -234,7 +235,7 @@ void CodaGdbAdapter::handleCodaRunControlModuleLoadContextSuspendedEvent(const C
|
||||
if (!localSymFileName.isEmpty()) {
|
||||
showMessage(msgLoadLocalSymFile(localSymFileName,
|
||||
library.name, library.codeseg), LogMisc);
|
||||
m_engine->postCommand(symFileLoadCommand(
|
||||
postCommand(symFileLoadCommand(
|
||||
localSymFileName, library.codeseg, library.dataseg));
|
||||
} // has local sym
|
||||
} // code seg
|
||||
@@ -271,11 +272,11 @@ void CodaGdbAdapter::handleCodaRunControlModuleLoadContextSuspendedEvent(const C
|
||||
// have to wait for the CODA startup to learn the load address.
|
||||
//m_engine->postCommand("add-symbol-file \"" + symbolFile + "\" "
|
||||
// + QByteArray::number(m_session.codeseg));
|
||||
m_engine->postCommand("symbol-file \"" + symbolFile + "\"");
|
||||
postCommand("symbol-file \"" + symbolFile + "\"");
|
||||
}
|
||||
foreach (const QByteArray &s, Symbian::gdbStartupSequence())
|
||||
m_engine->postCommand(s);
|
||||
m_engine->postCommand("target remote " + gdbServerName().toLatin1(),
|
||||
postCommand(s);
|
||||
postCommand("target remote " + gdbServerName().toLatin1(),
|
||||
CB(handleTargetRemote));
|
||||
if (debug)
|
||||
qDebug() << "Initial module load suspended: " << m_session.toString();
|
||||
@@ -286,32 +287,32 @@ void CodaGdbAdapter::handleCodaRunControlModuleLoadContextSuspendedEvent(const C
|
||||
}
|
||||
}
|
||||
|
||||
void CodaGdbAdapter::handleTargetRemote(const GdbResponse &record)
|
||||
void GdbCodaEngine::handleTargetRemote(const GdbResponse &record)
|
||||
{
|
||||
QTC_ASSERT(state() == InferiorSetupRequested, qDebug() << state());
|
||||
if (record.resultClass == GdbResultDone) {
|
||||
m_engine->handleInferiorPrepared();
|
||||
handleInferiorPrepared();
|
||||
if (debug)
|
||||
qDebug() << "handleTargetRemote" << m_session.toString();
|
||||
} else {
|
||||
QString msg = tr("Connecting to CODA server adapter failed:\n")
|
||||
+ QString::fromLocal8Bit(record.data.findChild("msg").data());
|
||||
m_engine->notifyInferiorSetupFailed(msg);
|
||||
notifyInferiorSetupFailed(msg);
|
||||
}
|
||||
}
|
||||
|
||||
void CodaGdbAdapter::codaDeviceRemoved(const SymbianUtils::SymbianDevice &dev)
|
||||
void GdbCodaEngine::codaDeviceRemoved(const SymbianUtils::SymbianDevice &dev)
|
||||
{
|
||||
const DebuggerStartParameters ¶meters = startParameters();
|
||||
if (state() != DebuggerNotReady && !m_codaDevice.isNull() && parameters.remoteChannel == dev.portName()) {
|
||||
const QString message = QString::fromLatin1("Device '%1' has been disconnected.").arg(dev.friendlyName());
|
||||
logMessage(message);
|
||||
m_engine->handleAdapterCrashed(message);
|
||||
handleAdapterCrashed(message);
|
||||
cleanup();
|
||||
}
|
||||
}
|
||||
|
||||
void CodaGdbAdapter::codaEvent(const CodaEvent &e)
|
||||
void GdbCodaEngine::codaEvent(const CodaEvent &e)
|
||||
{
|
||||
if (debug)
|
||||
qDebug() << e.toString() << m_session.toString() << m_snapshot.toString();
|
||||
@@ -322,7 +323,9 @@ void CodaGdbAdapter::codaEvent(const CodaEvent &e)
|
||||
if (state() == EngineSetupRequested && m_firstHelloEvent) {
|
||||
m_firstHelloEvent = false;
|
||||
m_codaDevice->sendLoggingAddListenerCommand(CodaCallback());
|
||||
startGdb(); // Commands are only accepted after hello
|
||||
QStringList gdbArgs;
|
||||
gdbArgs.append(_("--nx")); // Do not read .gdbinit file
|
||||
startGdb(gdbArgs); // Commands are only accepted after hello
|
||||
}
|
||||
break;
|
||||
case CodaEvent::RunControlModuleLoadSuspended: // A module was loaded
|
||||
@@ -369,7 +372,7 @@ void CodaGdbAdapter::codaEvent(const CodaEvent &e)
|
||||
|| reason.contains(_("panic"), Qt::CaseInsensitive) ?
|
||||
gdbServerSignalSegfault : gdbServerSignalTrap;
|
||||
m_codaDevice->sendRegistersGetMRangeCommand(
|
||||
CodaCallback(this, &CodaGdbAdapter::handleAndReportReadRegistersAfterStop),
|
||||
CodaCallback(this, &GdbCodaEngine::handleAndReportReadRegistersAfterStop),
|
||||
currentThreadContextId(), 0,
|
||||
Symbian::RegisterCount);
|
||||
}
|
||||
@@ -382,34 +385,22 @@ void CodaGdbAdapter::codaEvent(const CodaEvent &e)
|
||||
}
|
||||
}
|
||||
|
||||
void CodaGdbAdapter::startGdb()
|
||||
{
|
||||
QStringList gdbArgs;
|
||||
gdbArgs.append(_("--nx")); // Do not read .gdbinit file
|
||||
m_engine->startGdb(gdbArgs);
|
||||
}
|
||||
|
||||
void CodaGdbAdapter::handleGdbStartDone()
|
||||
{
|
||||
m_engine->handleAdapterStarted();
|
||||
}
|
||||
|
||||
void CodaGdbAdapter::handleGdbStartFailed()
|
||||
void GdbCodaEngine::handleGdbStartFailed()
|
||||
{
|
||||
cleanup();
|
||||
}
|
||||
|
||||
void CodaGdbAdapter::codaDeviceError(const QString &errorString)
|
||||
void GdbCodaEngine::codaDeviceError(const QString &errorString)
|
||||
{
|
||||
logMessage(errorString);
|
||||
if (state() == EngineSetupRequested) {
|
||||
m_engine->handleAdapterStartFailed(errorString);
|
||||
handleAdapterStartFailed(errorString);
|
||||
} else {
|
||||
m_engine->handleAdapterCrashed(errorString);
|
||||
handleAdapterCrashed(errorString);
|
||||
}
|
||||
}
|
||||
|
||||
void CodaGdbAdapter::logMessage(const QString &msg, int channel)
|
||||
void GdbCodaEngine::logMessage(const QString &msg, int channel)
|
||||
{
|
||||
if (m_verbose || channel != LogDebug)
|
||||
showMessage(msg, channel);
|
||||
@@ -420,7 +411,7 @@ void CodaGdbAdapter::logMessage(const QString &msg, int channel)
|
||||
//
|
||||
// Gdb
|
||||
//
|
||||
void CodaGdbAdapter::handleGdbConnection()
|
||||
void GdbCodaEngine::handleGdbConnection()
|
||||
{
|
||||
logMessage(QLatin1String("HANDLING GDB CONNECTION"));
|
||||
QTC_CHECK(m_gdbConnection == 0);
|
||||
@@ -437,7 +428,7 @@ static inline QString msgGdbPacket(const QString &p)
|
||||
return _("gdb: ") + p;
|
||||
}
|
||||
|
||||
void CodaGdbAdapter::readGdbServerCommand()
|
||||
void GdbCodaEngine::readGdbServerCommand()
|
||||
{
|
||||
QTC_ASSERT(m_gdbConnection, return);
|
||||
QByteArray packet = m_gdbConnection->readAll();
|
||||
@@ -508,7 +499,7 @@ void CodaGdbAdapter::readGdbServerCommand()
|
||||
}
|
||||
}
|
||||
|
||||
bool CodaGdbAdapter::sendGdbServerPacket(const QByteArray &packet, bool doFlush)
|
||||
bool GdbCodaEngine::sendGdbServerPacket(const QByteArray &packet, bool doFlush)
|
||||
{
|
||||
if (!m_gdbConnection) {
|
||||
logMessage(_("Cannot write to gdb: No connection (%1)")
|
||||
@@ -530,7 +521,7 @@ bool CodaGdbAdapter::sendGdbServerPacket(const QByteArray &packet, bool doFlush)
|
||||
return true;
|
||||
}
|
||||
|
||||
void CodaGdbAdapter::sendGdbServerAck()
|
||||
void GdbCodaEngine::sendGdbServerAck()
|
||||
{
|
||||
if (!m_gdbAckMode)
|
||||
return;
|
||||
@@ -538,7 +529,7 @@ void CodaGdbAdapter::sendGdbServerAck()
|
||||
sendGdbServerPacket(QByteArray(1, '+'), false);
|
||||
}
|
||||
|
||||
void CodaGdbAdapter::sendGdbServerMessage(const QByteArray &msg, const QByteArray &logNote)
|
||||
void GdbCodaEngine::sendGdbServerMessage(const QByteArray &msg, const QByteArray &logNote)
|
||||
{
|
||||
Coda::byte sum = 0;
|
||||
for (int i = 0; i != msg.size(); ++i)
|
||||
@@ -573,7 +564,7 @@ static QByteArray msgStepRangeReceived(unsigned from, unsigned to, bool over)
|
||||
return rc;
|
||||
}
|
||||
|
||||
void CodaGdbAdapter::handleGdbServerCommand(const QByteArray &cmd)
|
||||
void GdbCodaEngine::handleGdbServerCommand(const QByteArray &cmd)
|
||||
{
|
||||
if (debug)
|
||||
qDebug("handleGdbServerCommand: %s", cmd.constData());
|
||||
@@ -720,7 +711,7 @@ void CodaGdbAdapter::handleGdbServerCommand(const QByteArray &cmd)
|
||||
arg(addrLength.second).arg(addrLength.first, 0, 16).
|
||||
arg(QString::fromLatin1(data.toHex())));
|
||||
m_codaDevice->sendMemorySetCommand(
|
||||
CodaCallback(this, &CodaGdbAdapter::handleWriteMemory),
|
||||
CodaCallback(this, &GdbCodaEngine::handleWriteMemory),
|
||||
m_codaProcessId, addrLength.first, data);
|
||||
}
|
||||
|
||||
@@ -740,7 +731,7 @@ void CodaGdbAdapter::handleGdbServerCommand(const QByteArray &cmd)
|
||||
} else {
|
||||
//qDebug() << "Fetching single register";
|
||||
m_codaDevice->sendRegistersGetMRangeCommand(
|
||||
CodaCallback(this, &CodaGdbAdapter::handleAndReportReadRegister),
|
||||
CodaCallback(this, &GdbCodaEngine::handleAndReportReadRegister),
|
||||
currentThreadContextId(), registerNumber, 1);
|
||||
}
|
||||
}
|
||||
@@ -757,7 +748,7 @@ void CodaGdbAdapter::handleGdbServerCommand(const QByteArray &cmd)
|
||||
QByteArray registerValue;
|
||||
Coda::appendInt(®isterValue, Coda::BigEndian); // Registers are big endian
|
||||
m_codaDevice->sendRegistersSetCommand(
|
||||
CodaCallback(this, &CodaGdbAdapter::handleWriteRegister),
|
||||
CodaCallback(this, &GdbCodaEngine::handleWriteRegister),
|
||||
currentThreadContextId(), regnumValue.first, registerValue,
|
||||
QVariant(regnumValue.first));
|
||||
// Note that App CODA refuses to write registers 13 and 14
|
||||
@@ -938,7 +929,7 @@ void CodaGdbAdapter::handleGdbServerCommand(const QByteArray &cmd)
|
||||
// We use the automatic ids calculated from the location
|
||||
// address instead of the map in snapshot.
|
||||
m_codaDevice->sendBreakpointsAddCommand(
|
||||
CodaCallback(this, &CodaGdbAdapter::handleAndReportSetBreakpoint),
|
||||
CodaCallback(this, &GdbCodaEngine::handleAndReportSetBreakpoint),
|
||||
bp);
|
||||
} else {
|
||||
logMessage(_("MISPARSED BREAKPOINT '") + QLatin1String(cmd)
|
||||
@@ -954,7 +945,7 @@ void CodaGdbAdapter::handleGdbServerCommand(const QByteArray &cmd)
|
||||
const int pos = cmd.lastIndexOf(',');
|
||||
const uint addr = cmd.mid(3, pos - 3).toUInt(0, 16);
|
||||
m_codaDevice->sendBreakpointsRemoveCommand(
|
||||
CodaCallback(this, &CodaGdbAdapter::handleClearBreakpoint),
|
||||
CodaCallback(this, &GdbCodaEngine::handleClearBreakpoint),
|
||||
Coda::Breakpoint::idFromLocation(addr));
|
||||
}
|
||||
|
||||
@@ -994,17 +985,17 @@ void CodaGdbAdapter::handleGdbServerCommand(const QByteArray &cmd)
|
||||
}
|
||||
}
|
||||
|
||||
void CodaGdbAdapter::sendRunControlTerminateCommand()
|
||||
void GdbCodaEngine::sendRunControlTerminateCommand()
|
||||
{
|
||||
// Requires id of main thread to terminate.
|
||||
// Note that calling 'Settings|set|removeExecutable' crashes CODA,
|
||||
// so, it is apparently not required.
|
||||
m_codaDevice->sendRunControlTerminateCommand(
|
||||
CodaCallback(this, &CodaGdbAdapter::handleRunControlTerminate),
|
||||
CodaCallback(this, &GdbCodaEngine::handleRunControlTerminate),
|
||||
mainThreadContextId());
|
||||
}
|
||||
|
||||
void CodaGdbAdapter::handleRunControlTerminate(const CodaCommandResult &)
|
||||
void GdbCodaEngine::handleRunControlTerminate(const CodaCommandResult &)
|
||||
{
|
||||
QString msg = QString::fromLatin1("CODA disconnected");
|
||||
const bool emergencyShutdown = m_gdbProc.state() != QProcess::Running
|
||||
@@ -1014,11 +1005,11 @@ void CodaGdbAdapter::handleRunControlTerminate(const CodaCommandResult &)
|
||||
logMessage(msg, LogMisc);
|
||||
if (emergencyShutdown) {
|
||||
cleanup();
|
||||
m_engine->notifyAdapterShutdownOk();
|
||||
notifyAdapterShutdownOk();
|
||||
}
|
||||
}
|
||||
|
||||
void CodaGdbAdapter::gdbSetCurrentThread(const QByteArray &cmd, const char *why)
|
||||
void GdbCodaEngine::gdbSetCurrentThread(const QByteArray &cmd, const char *why)
|
||||
{
|
||||
// Thread ID from Hg/Hc commands: '-1': All, '0': arbitrary, else hex thread id.
|
||||
const QByteArray id = cmd.mid(2);
|
||||
@@ -1032,12 +1023,12 @@ void CodaGdbAdapter::gdbSetCurrentThread(const QByteArray &cmd, const char *why)
|
||||
sendGdbServerMessage("OK", message);
|
||||
}
|
||||
|
||||
void CodaGdbAdapter::interruptInferior()
|
||||
void GdbCodaEngine::interruptInferior2()
|
||||
{
|
||||
m_codaDevice->sendRunControlSuspendCommand(CodaCallback(), m_codaProcessId);
|
||||
}
|
||||
|
||||
void CodaGdbAdapter::startAdapter()
|
||||
void GdbCodaEngine::setupEngine()
|
||||
{
|
||||
m_snapshot.fullReset();
|
||||
m_session.reset();
|
||||
@@ -1072,7 +1063,7 @@ void CodaGdbAdapter::startAdapter()
|
||||
const QString msg = QString::fromLatin1("Could not open serial device '%1': %2")
|
||||
.arg(parameters.remoteChannel, reason);
|
||||
logMessage(msg, LogError);
|
||||
m_engine->handleAdapterStartFailed(msg);
|
||||
handleAdapterStartFailed(msg);
|
||||
return;
|
||||
}
|
||||
setupDeviceSignals();
|
||||
@@ -1104,7 +1095,7 @@ void CodaGdbAdapter::startAdapter()
|
||||
QString msg = QString::fromLatin1("Unable to start the gdb server at %1: %2.")
|
||||
.arg(m_gdbServerName).arg(m_gdbServer->errorString());
|
||||
logMessage(msg, LogError);
|
||||
m_engine->handleAdapterStartFailed(msg);
|
||||
handleAdapterStartFailed(msg);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1124,7 +1115,7 @@ void CodaGdbAdapter::startAdapter()
|
||||
}
|
||||
}
|
||||
|
||||
void CodaGdbAdapter::setupInferior()
|
||||
void GdbCodaEngine::setupInferior()
|
||||
{
|
||||
QTC_ASSERT(state() == InferiorSetupRequested, qDebug() << state());
|
||||
|
||||
@@ -1135,12 +1126,12 @@ void CodaGdbAdapter::setupInferior()
|
||||
libraries.push_back(QString::fromLatin1(librariesC[i]));
|
||||
|
||||
m_codaDevice->sendProcessStartCommand(
|
||||
CodaCallback(this, &CodaGdbAdapter::handleCreateProcess),
|
||||
CodaCallback(this, &GdbCodaEngine::handleCreateProcess),
|
||||
m_remoteExecutable, m_uid, m_remoteArguments,
|
||||
QString(), true, libraries);
|
||||
}
|
||||
|
||||
void CodaGdbAdapter::addThread(unsigned id)
|
||||
void GdbCodaEngine::addThread(unsigned id)
|
||||
{
|
||||
showMessage(QString::fromLatin1("Thread %1 reported").arg(id), LogMisc);
|
||||
// Make thread known, register as main if it is the first one.
|
||||
@@ -1155,19 +1146,19 @@ void CodaGdbAdapter::addThread(unsigned id)
|
||||
// thread have been retrieved (CODA oddity).
|
||||
const QByteArray contextId = RunControlContext::codaId(m_session.pid, id);
|
||||
m_codaDevice->sendRegistersGetChildrenCommand(
|
||||
CodaCallback(this, &CodaGdbAdapter::handleRegisterChildren),
|
||||
CodaCallback(this, &GdbCodaEngine::handleRegisterChildren),
|
||||
contextId, QVariant(contextId));
|
||||
}
|
||||
}
|
||||
|
||||
void CodaGdbAdapter::handleCreateProcess(const CodaCommandResult &result)
|
||||
void GdbCodaEngine::handleCreateProcess(const CodaCommandResult &result)
|
||||
{
|
||||
if (debug)
|
||||
qDebug() << "ProcessCreated: " << result.toString();
|
||||
if (!result) {
|
||||
const QString errorMessage = result.errorString();
|
||||
logMessage(_("Failed to start process: %1").arg(errorMessage), LogError);
|
||||
m_engine->notifyInferiorSetupFailed(result.errorString());
|
||||
notifyInferiorSetupFailed(result.errorString());
|
||||
return;
|
||||
}
|
||||
QTC_ASSERT(!result.values.isEmpty(), return);
|
||||
@@ -1185,19 +1176,19 @@ void CodaGdbAdapter::handleCreateProcess(const CodaCommandResult &result)
|
||||
m_session.dataseg = 0;
|
||||
}
|
||||
|
||||
void CodaGdbAdapter::runEngine()
|
||||
void GdbCodaEngine::runEngine()
|
||||
{
|
||||
QTC_ASSERT(state() == EngineRunRequested, qDebug() << state());
|
||||
m_engine->notifyEngineRunAndInferiorStopOk();
|
||||
notifyEngineRunAndInferiorStopOk();
|
||||
// Trigger the initial "continue" manually.
|
||||
m_engine->continueInferiorInternal();
|
||||
continueInferiorInternal();
|
||||
}
|
||||
|
||||
//
|
||||
// AbstractGdbAdapter interface implementation
|
||||
//
|
||||
|
||||
void CodaGdbAdapter::write(const QByteArray &data)
|
||||
void GdbCodaEngine::write(const QByteArray &data)
|
||||
{
|
||||
// Write magic packets directly to TRK.
|
||||
if (data.startsWith("@#")) {
|
||||
@@ -1229,7 +1220,7 @@ void CodaGdbAdapter::write(const QByteArray &data)
|
||||
m_gdbProc.write(data);
|
||||
}
|
||||
|
||||
void CodaGdbAdapter::cleanup()
|
||||
void GdbCodaEngine::cleanup()
|
||||
{
|
||||
delete m_gdbServer;
|
||||
m_gdbServer = 0;
|
||||
@@ -1243,11 +1234,11 @@ void CodaGdbAdapter::cleanup()
|
||||
}
|
||||
}
|
||||
|
||||
void CodaGdbAdapter::shutdownAdapter()
|
||||
void GdbCodaEngine::shutdownEngine()
|
||||
{
|
||||
if (m_gdbProc.state() == QProcess::Running) {
|
||||
cleanup();
|
||||
m_engine->notifyAdapterShutdownOk();
|
||||
notifyAdapterShutdownOk();
|
||||
} else {
|
||||
// Something is wrong, gdb crashed. Kill debuggee (see handleDeleteProcess2)
|
||||
if (m_codaDevice && m_codaDevice->device()->isOpen()) {
|
||||
@@ -1257,18 +1248,18 @@ void CodaGdbAdapter::shutdownAdapter()
|
||||
}
|
||||
}
|
||||
|
||||
void CodaGdbAdapter::codaReloadRegisters()
|
||||
void GdbCodaEngine::codaReloadRegisters()
|
||||
{
|
||||
// Take advantage of direct access to cached register values.
|
||||
m_snapshot.syncRegisters(m_session.tid, m_engine->registerHandler());
|
||||
m_snapshot.syncRegisters(m_session.tid, registerHandler());
|
||||
}
|
||||
|
||||
void CodaGdbAdapter::codaReloadThreads()
|
||||
void GdbCodaEngine::codaReloadThreads()
|
||||
{
|
||||
m_snapshot.syncThreads(m_engine->threadsHandler());
|
||||
m_snapshot.syncThreads(threadsHandler());
|
||||
}
|
||||
|
||||
void CodaGdbAdapter::handleWriteRegister(const CodaCommandResult &result)
|
||||
void GdbCodaEngine::handleWriteRegister(const CodaCommandResult &result)
|
||||
{
|
||||
const int registerNumber = result.cookie.toInt();
|
||||
if (result) {
|
||||
@@ -1280,18 +1271,18 @@ void CodaGdbAdapter::handleWriteRegister(const CodaCommandResult &result)
|
||||
}
|
||||
}
|
||||
|
||||
void CodaGdbAdapter::sendRegistersGetMCommand()
|
||||
void GdbCodaEngine::sendRegistersGetMCommand()
|
||||
{
|
||||
// Send off a register command, which requires the names to be present.
|
||||
QTC_ASSERT(!m_codaDevice->registerNames().isEmpty(), return);
|
||||
|
||||
m_codaDevice->sendRegistersGetMRangeCommand(
|
||||
CodaCallback(this, &CodaGdbAdapter::handleAndReportReadRegisters),
|
||||
CodaCallback(this, &GdbCodaEngine::handleAndReportReadRegisters),
|
||||
currentThreadContextId(), 0,
|
||||
Symbian::RegisterCount);
|
||||
}
|
||||
|
||||
void CodaGdbAdapter::reportRegisters()
|
||||
void GdbCodaEngine::reportRegisters()
|
||||
{
|
||||
const int threadIndex = m_snapshot.indexOfThread(m_session.tid);
|
||||
QTC_ASSERT(threadIndex != -1, return);
|
||||
@@ -1300,7 +1291,7 @@ void CodaGdbAdapter::reportRegisters()
|
||||
thread.gdbRegisterLogMessage(m_verbose));
|
||||
}
|
||||
|
||||
void CodaGdbAdapter::handleRegisterChildren(const CodaCommandResult &result)
|
||||
void GdbCodaEngine::handleRegisterChildren(const CodaCommandResult &result)
|
||||
{
|
||||
QTC_ASSERT(m_codaDevice, return);
|
||||
const QByteArray contextId = result.cookie.toByteArray();
|
||||
@@ -1317,7 +1308,7 @@ void CodaGdbAdapter::handleRegisterChildren(const CodaCommandResult &result)
|
||||
QVector<QByteArray> registerNames = CodaDevice::parseRegisterGetChildren(result);
|
||||
if (registerNames.size() == 1) {
|
||||
m_codaDevice->sendRegistersGetChildrenCommand(
|
||||
CodaCallback(this, &CodaGdbAdapter::handleRegisterChildren),
|
||||
CodaCallback(this, &GdbCodaEngine::handleRegisterChildren),
|
||||
registerNames.front(), result.cookie);
|
||||
return;
|
||||
}
|
||||
@@ -1348,7 +1339,7 @@ void CodaGdbAdapter::handleRegisterChildren(const CodaCommandResult &result)
|
||||
}
|
||||
}
|
||||
|
||||
void CodaGdbAdapter::handleReadRegisters(const CodaCommandResult &result)
|
||||
void GdbCodaEngine::handleReadRegisters(const CodaCommandResult &result)
|
||||
{
|
||||
// Check for errors.
|
||||
if (!result) {
|
||||
@@ -1382,13 +1373,13 @@ void CodaGdbAdapter::handleReadRegisters(const CodaCommandResult &result)
|
||||
qDebug() << "handleReadRegisters: " << m_snapshot.toString();
|
||||
}
|
||||
|
||||
void CodaGdbAdapter::handleAndReportReadRegisters(const CodaCommandResult &result)
|
||||
void GdbCodaEngine::handleAndReportReadRegisters(const CodaCommandResult &result)
|
||||
{
|
||||
handleReadRegisters(result);
|
||||
reportRegisters();
|
||||
}
|
||||
|
||||
void CodaGdbAdapter::handleAndReportReadRegister(const CodaCommandResult &result)
|
||||
void GdbCodaEngine::handleAndReportReadRegister(const CodaCommandResult &result)
|
||||
{
|
||||
handleReadRegisters(result);
|
||||
const uint registerNumber = result.cookie.toUInt();
|
||||
@@ -1399,7 +1390,7 @@ void CodaGdbAdapter::handleAndReportReadRegister(const CodaCommandResult &result
|
||||
thread.gdbSingleRegisterLogMessage(registerNumber));
|
||||
}
|
||||
|
||||
QByteArray CodaGdbAdapter::stopMessage() const
|
||||
QByteArray GdbCodaEngine::stopMessage() const
|
||||
{
|
||||
QByteArray logMsg = "Stopped with registers in thread 0x";
|
||||
logMsg += QByteArray::number(m_session.tid, 16);
|
||||
@@ -1420,7 +1411,7 @@ QByteArray CodaGdbAdapter::stopMessage() const
|
||||
return logMsg;
|
||||
}
|
||||
|
||||
void CodaGdbAdapter::handleAndReportReadRegistersAfterStop(const CodaCommandResult &result)
|
||||
void GdbCodaEngine::handleAndReportReadRegistersAfterStop(const CodaCommandResult &result)
|
||||
{
|
||||
handleReadRegisters(result);
|
||||
handleReadRegisters(result);
|
||||
@@ -1429,7 +1420,7 @@ void CodaGdbAdapter::handleAndReportReadRegistersAfterStop(const CodaCommandResu
|
||||
m_stopReason, reportThread), stopMessage());
|
||||
}
|
||||
|
||||
void CodaGdbAdapter::handleAndReportSetBreakpoint(const CodaCommandResult &result)
|
||||
void GdbCodaEngine::handleAndReportSetBreakpoint(const CodaCommandResult &result)
|
||||
{
|
||||
if (result) {
|
||||
sendGdbServerMessage("OK");
|
||||
@@ -1439,7 +1430,7 @@ void CodaGdbAdapter::handleAndReportSetBreakpoint(const CodaCommandResult &resul
|
||||
}
|
||||
}
|
||||
|
||||
void CodaGdbAdapter::handleClearBreakpoint(const CodaCommandResult &result)
|
||||
void GdbCodaEngine::handleClearBreakpoint(const CodaCommandResult &result)
|
||||
{
|
||||
logMessage(QLatin1String("CLEAR BREAKPOINT "));
|
||||
if (!result)
|
||||
@@ -1448,7 +1439,7 @@ void CodaGdbAdapter::handleClearBreakpoint(const CodaCommandResult &result)
|
||||
sendGdbServerMessage("OK");
|
||||
}
|
||||
|
||||
void CodaGdbAdapter::readMemory(uint addr, uint len, bool buffered)
|
||||
void GdbCodaEngine::readMemory(uint addr, uint len, bool buffered)
|
||||
{
|
||||
Q_ASSERT(len < (2 << 16));
|
||||
|
||||
@@ -1467,16 +1458,16 @@ static QString msgMemoryReadError(uint addr, uint len = 0)
|
||||
return _("Memory read error at: 0x%1 %2").arg(addr, 0, 16).arg(lenS);
|
||||
}
|
||||
|
||||
void CodaGdbAdapter::sendMemoryGetCommand(const MemoryRange &range, bool buffered)
|
||||
void GdbCodaEngine::sendMemoryGetCommand(const MemoryRange &range, bool buffered)
|
||||
{
|
||||
const QVariant cookie = QVariant::fromValue(range);
|
||||
const CodaCallback cb = buffered ?
|
||||
CodaCallback(this, &CodaGdbAdapter::handleReadMemoryBuffered) :
|
||||
CodaCallback(this, &CodaGdbAdapter::handleReadMemoryUnbuffered);
|
||||
CodaCallback(this, &GdbCodaEngine::handleReadMemoryBuffered) :
|
||||
CodaCallback(this, &GdbCodaEngine::handleReadMemoryUnbuffered);
|
||||
m_codaDevice->sendMemoryGetCommand(cb, currentThreadContextId(), range.from, range.size(), cookie);
|
||||
}
|
||||
|
||||
void CodaGdbAdapter::handleReadMemoryBuffered(const CodaCommandResult &result)
|
||||
void GdbCodaEngine::handleReadMemoryBuffered(const CodaCommandResult &result)
|
||||
{
|
||||
QTC_ASSERT(qVariantCanConvert<MemoryRange>(result.cookie), return);
|
||||
|
||||
@@ -1502,7 +1493,7 @@ void CodaGdbAdapter::handleReadMemoryBuffered(const CodaCommandResult &result)
|
||||
tryAnswerGdbMemoryRequest(true);
|
||||
}
|
||||
|
||||
void CodaGdbAdapter::handleReadMemoryUnbuffered(const CodaCommandResult &result)
|
||||
void GdbCodaEngine::handleReadMemoryUnbuffered(const CodaCommandResult &result)
|
||||
{
|
||||
QTC_ASSERT(qVariantCanConvert<MemoryRange>(result.cookie), return);
|
||||
|
||||
@@ -1526,7 +1517,7 @@ void CodaGdbAdapter::handleReadMemoryUnbuffered(const CodaCommandResult &result)
|
||||
tryAnswerGdbMemoryRequest(false);
|
||||
}
|
||||
|
||||
void CodaGdbAdapter::tryAnswerGdbMemoryRequest(bool buffered)
|
||||
void GdbCodaEngine::tryAnswerGdbMemoryRequest(bool buffered)
|
||||
{
|
||||
//logMessage("TRYING TO ANSWER MEMORY REQUEST ");
|
||||
MemoryRange wanted = m_snapshot.wantedMemory;
|
||||
@@ -1588,7 +1579,7 @@ void CodaGdbAdapter::tryAnswerGdbMemoryRequest(bool buffered)
|
||||
}
|
||||
}
|
||||
|
||||
void CodaGdbAdapter::handleWriteMemory(const CodaCommandResult &result)
|
||||
void GdbCodaEngine::handleWriteMemory(const CodaCommandResult &result)
|
||||
{
|
||||
if (result) {
|
||||
sendGdbServerMessage("OK", "Write memory");
|
||||
@@ -1598,17 +1589,17 @@ void CodaGdbAdapter::handleWriteMemory(const CodaCommandResult &result)
|
||||
}
|
||||
}
|
||||
|
||||
QByteArray CodaGdbAdapter::mainThreadContextId() const
|
||||
QByteArray GdbCodaEngine::mainThreadContextId() const
|
||||
{
|
||||
return RunControlContext::codaId(m_session.pid, m_session.mainTid);
|
||||
}
|
||||
|
||||
QByteArray CodaGdbAdapter::currentThreadContextId() const
|
||||
QByteArray GdbCodaEngine::currentThreadContextId() const
|
||||
{
|
||||
return RunControlContext::codaId(m_session.pid, m_session.tid);
|
||||
}
|
||||
|
||||
void CodaGdbAdapter::sendContinue()
|
||||
void GdbCodaEngine::sendContinue()
|
||||
{
|
||||
// Remove all but main thread as we do not know whether they will exist
|
||||
// at the next stop.
|
||||
@@ -1617,7 +1608,7 @@ void CodaGdbAdapter::sendContinue()
|
||||
m_codaDevice->sendRunControlResumeCommand(CodaCallback(), m_codaProcessId);
|
||||
}
|
||||
|
||||
void CodaGdbAdapter::sendStepRange()
|
||||
void GdbCodaEngine::sendStepRange()
|
||||
{
|
||||
uint from = m_snapshot.lineFromAddress;
|
||||
uint to = m_snapshot.lineToAddress;
|
||||
@@ -1638,12 +1629,12 @@ void CodaGdbAdapter::sendStepRange()
|
||||
logMessage(_("Stepping from 0x%1 to 0x%2 (current PC=0x%3), mode %4").
|
||||
arg(from, 0, 16).arg(to, 0, 16).arg(pc).arg(int(mode)));
|
||||
m_codaDevice->sendRunControlResumeCommand(
|
||||
CodaCallback(this, &CodaGdbAdapter::handleStep),
|
||||
CodaCallback(this, &GdbCodaEngine::handleStep),
|
||||
currentThreadContextId(),
|
||||
mode, 1, from, to);
|
||||
}
|
||||
|
||||
void CodaGdbAdapter::handleStep(const CodaCommandResult &result)
|
||||
void GdbCodaEngine::handleStep(const CodaCommandResult &result)
|
||||
{
|
||||
if (!result) { // Try fallback with Continue.
|
||||
logMessage(QString::fromLatin1("Error while stepping: %1 (fallback to 'continue')").
|
||||
|
||||
@@ -33,7 +33,7 @@
|
||||
#ifndef DEBUGGER_CODAGDBADAPTER_H
|
||||
#define DEBUGGER_CODAGDBADAPTER_H
|
||||
|
||||
#include "abstractgdbadapter.h"
|
||||
#include "gdbengine.h"
|
||||
#include "localgdbprocess.h"
|
||||
#include "callback.h"
|
||||
#include "codautils.h"
|
||||
@@ -73,7 +73,7 @@ struct GdbResult;
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
|
||||
class CodaGdbAdapter : public AbstractGdbAdapter
|
||||
class GdbCodaEngine : public GdbEngine
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
@@ -82,8 +82,10 @@ public:
|
||||
typedef Coda::Callback<const Coda::CodaCommandResult &> CodaCallback;
|
||||
typedef Coda::Callback<const GdbResponse &> GdbCallback;
|
||||
|
||||
explicit CodaGdbAdapter(GdbEngine *engine);
|
||||
~CodaGdbAdapter();
|
||||
GdbCodaEngine(const DebuggerStartParameters &startParameters,
|
||||
DebuggerEngine *masterEngine);
|
||||
~GdbCodaEngine();
|
||||
|
||||
void setGdbServerName(const QString &name);
|
||||
QString gdbServerName() const { return m_gdbServerName; }
|
||||
|
||||
@@ -110,13 +112,12 @@ public:
|
||||
|
||||
private:
|
||||
void setupDeviceSignals();
|
||||
void startAdapter();
|
||||
void handleGdbStartDone();
|
||||
void setupEngine();
|
||||
void handleGdbStartFailed();
|
||||
void setupInferior();
|
||||
void runEngine();
|
||||
void interruptInferior();
|
||||
void shutdownAdapter();
|
||||
void interruptInferior2();
|
||||
void shutdownEngine();
|
||||
void sendRunControlTerminateCommand();
|
||||
void handleRunControlTerminate(const Coda::CodaCommandResult &);
|
||||
void sendRegistersGetMCommand();
|
||||
@@ -159,8 +160,6 @@ private:
|
||||
Q_SLOT void readGdbServerCommand();
|
||||
Q_SLOT void codaDeviceError(const QString &);
|
||||
Q_SLOT void codaDeviceRemoved(const SymbianUtils::SymbianDevice &dev);
|
||||
|
||||
void startGdb();
|
||||
Q_SLOT void codaEvent(const Coda::CodaEvent &knownEvent);
|
||||
void handleCodaRunControlModuleLoadContextSuspendedEvent(const Coda::CodaRunControlModuleLoadContextSuspendedEvent &e);
|
||||
inline void sendContinue();
|
||||
|
||||
@@ -56,7 +56,7 @@ namespace Debugger {
|
||||
namespace Internal {
|
||||
|
||||
#define CB(callback) \
|
||||
static_cast<GdbEngine::AdapterCallback>(&CoreGdbAdapter::callback), \
|
||||
static_cast<GdbEngine::GdbCommandCallback>(&GdbCoreEngine::callback), \
|
||||
STRINGIFY(callback)
|
||||
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
@@ -65,11 +65,12 @@ namespace Internal {
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
|
||||
CoreGdbAdapter::CoreGdbAdapter(GdbEngine *engine)
|
||||
: AbstractGdbAdapter(engine)
|
||||
GdbCoreEngine::GdbCoreEngine(const DebuggerStartParameters &startParameters,
|
||||
DebuggerEngine *masterEngine)
|
||||
: GdbEngine(startParameters, masterEngine)
|
||||
{}
|
||||
|
||||
CoreGdbAdapter::~CoreGdbAdapter()
|
||||
GdbCoreEngine::~GdbCoreEngine()
|
||||
{
|
||||
if (false && !m_tempCoreName.isEmpty()) {
|
||||
QFile tmpFile(m_tempCoreName);
|
||||
@@ -77,7 +78,7 @@ CoreGdbAdapter::~CoreGdbAdapter()
|
||||
}
|
||||
}
|
||||
|
||||
void CoreGdbAdapter::startAdapter()
|
||||
void GdbCoreEngine::setupEngine()
|
||||
{
|
||||
QTC_ASSERT(state() == EngineSetupRequested, qDebug() << state());
|
||||
showMessage(_("TRYING TO START ADAPTER"));
|
||||
@@ -90,7 +91,7 @@ void CoreGdbAdapter::startAdapter()
|
||||
unpackCoreIfNeeded();
|
||||
}
|
||||
|
||||
void CoreGdbAdapter::continueAdapterStart()
|
||||
void GdbCoreEngine::continueSetupEngine()
|
||||
{
|
||||
if (m_executable.isEmpty()) {
|
||||
// Read executable from core.
|
||||
@@ -102,7 +103,7 @@ void CoreGdbAdapter::continueAdapterStart()
|
||||
showMessageBox(QMessageBox::Warning,
|
||||
tr("Error Loading Core File"),
|
||||
tr("The specified file does not appear to be a core file."));
|
||||
m_engine->notifyEngineSetupFailed();
|
||||
notifyEngineSetupFailed();
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -114,46 +115,30 @@ void CoreGdbAdapter::continueAdapterStart()
|
||||
showMessageBox(QMessageBox::Warning,
|
||||
tr("Error Loading Symbols"),
|
||||
tr("No executable to load symbols from specified core."));
|
||||
m_engine->notifyEngineSetupFailed();
|
||||
notifyEngineSetupFailed();
|
||||
return;
|
||||
}
|
||||
}
|
||||
m_engine->startGdb();
|
||||
startGdb();
|
||||
}
|
||||
|
||||
void CoreGdbAdapter::handleGdbStartFailed()
|
||||
{
|
||||
}
|
||||
|
||||
void CoreGdbAdapter::handleGdbStartDone()
|
||||
{
|
||||
m_engine->handleAdapterStarted();
|
||||
}
|
||||
|
||||
void CoreGdbAdapter::setupInferior()
|
||||
void GdbCoreEngine::setupInferior()
|
||||
{
|
||||
QTC_ASSERT(state() == InferiorSetupRequested, qDebug() << state());
|
||||
// Do that first, otherwise no symbols are loaded.
|
||||
QFileInfo fi(m_executable);
|
||||
const QByteArray sysroot = startParameters().sysroot.toLocal8Bit();
|
||||
QByteArray path = fi.absoluteFilePath().toLocal8Bit();
|
||||
if (!sysroot.isEmpty()) {
|
||||
m_engine->postCommand("set sysroot " + sysroot);
|
||||
// sysroot is not enough to correctly locate the sources, so explicitly
|
||||
// relocate the most likely place for the debug source
|
||||
m_engine->postCommand("set substitute-path /usr/src " + sysroot + "/usr/src");
|
||||
}
|
||||
m_engine->postCommand("-file-exec-and-symbols \"" + path + '"',
|
||||
postCommand("-file-exec-and-symbols \"" + path + '"',
|
||||
CB(handleFileExecAndSymbols));
|
||||
}
|
||||
|
||||
void CoreGdbAdapter::handleFileExecAndSymbols(const GdbResponse &response)
|
||||
void GdbCoreEngine::handleFileExecAndSymbols(const GdbResponse &response)
|
||||
{
|
||||
QTC_ASSERT(state() == InferiorSetupRequested, qDebug() << state());
|
||||
QString core = coreFileName();
|
||||
if (response.resultClass == GdbResultDone) {
|
||||
showMessage(tr("Symbols found."), StatusBar);
|
||||
m_engine->postCommand("target core " + core.toLocal8Bit(),
|
||||
postCommand("target core " + core.toLocal8Bit(),
|
||||
CB(handleTargetCore));
|
||||
return;
|
||||
}
|
||||
@@ -165,68 +150,59 @@ void CoreGdbAdapter::handleFileExecAndSymbols(const GdbResponse &response)
|
||||
msg += _(" ");
|
||||
msg += tr("Try to specify the binary using the "
|
||||
"<i>Debug->Start Debugging->Attach to Core</i> dialog.");
|
||||
m_engine->notifyInferiorSetupFailed(msg);
|
||||
notifyInferiorSetupFailed(msg);
|
||||
}
|
||||
|
||||
void CoreGdbAdapter::handleTargetCore(const GdbResponse &response)
|
||||
void GdbCoreEngine::handleTargetCore(const GdbResponse &response)
|
||||
{
|
||||
QTC_ASSERT(state() == InferiorSetupRequested, qDebug() << state());
|
||||
if (response.resultClass == GdbResultDone) {
|
||||
// HACK: The namespace is not accessible in the initial run.
|
||||
m_engine->loadPythonDumpers();
|
||||
loadPythonDumpers();
|
||||
showMessage(tr("Attached to core."), StatusBar);
|
||||
m_engine->handleInferiorPrepared();
|
||||
handleInferiorPrepared();
|
||||
// Due to the auto-solib-add off setting, we don't have any
|
||||
// symbols yet. Load them in order of importance.
|
||||
m_engine->reloadStack(true);
|
||||
m_engine->postCommand("info shared", CB(handleModulesList));
|
||||
reloadStack(true);
|
||||
reloadModulesInternal();
|
||||
postCommand("p 5", CB(handleRoundTrip));
|
||||
return;
|
||||
}
|
||||
QString msg = tr("Attach to core \"%1\" failed:\n")
|
||||
.arg(startParameters().coreFile)
|
||||
+ QString::fromLocal8Bit(response.data.findChild("msg").data());
|
||||
m_engine->notifyInferiorSetupFailed(msg);
|
||||
notifyInferiorSetupFailed(msg);
|
||||
}
|
||||
|
||||
void CoreGdbAdapter::handleModulesList(const GdbResponse &response)
|
||||
void GdbCoreEngine::handleRoundTrip(const GdbResponse &response)
|
||||
{
|
||||
m_engine->handleModulesList(response);
|
||||
Q_UNUSED(response);
|
||||
loadSymbolsForStack();
|
||||
}
|
||||
|
||||
void CoreGdbAdapter::loadSymbolsForStack()
|
||||
{
|
||||
m_engine->loadSymbolsForStack();
|
||||
QTimer::singleShot(1000, this, SLOT(loadAllSymbols()));
|
||||
}
|
||||
|
||||
void CoreGdbAdapter::loadAllSymbols()
|
||||
{
|
||||
m_engine->loadAllSymbols();
|
||||
}
|
||||
|
||||
void CoreGdbAdapter::runEngine()
|
||||
void GdbCoreEngine::runEngine()
|
||||
{
|
||||
QTC_ASSERT(state() == EngineRunRequested, qDebug() << state());
|
||||
m_engine->notifyInferiorUnrunnable();
|
||||
m_engine->updateAll();
|
||||
notifyInferiorUnrunnable();
|
||||
updateAll();
|
||||
}
|
||||
|
||||
void CoreGdbAdapter::interruptInferior()
|
||||
void GdbCoreEngine::interruptInferior()
|
||||
{
|
||||
// A core never runs, so this cannot be called.
|
||||
QTC_CHECK(false);
|
||||
}
|
||||
|
||||
void CoreGdbAdapter::shutdownAdapter()
|
||||
void GdbCoreEngine::shutdownEngine()
|
||||
{
|
||||
m_engine->notifyAdapterShutdownOk();
|
||||
notifyAdapterShutdownOk();
|
||||
}
|
||||
|
||||
void CoreGdbAdapter::unpackCoreIfNeeded()
|
||||
void GdbCoreEngine::unpackCoreIfNeeded()
|
||||
{
|
||||
if (!m_coreName.endsWith(QLatin1String(".lzo"))) {
|
||||
continueAdapterStart();
|
||||
continueSetupEngine();
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -240,10 +216,10 @@ void CoreGdbAdapter::unpackCoreIfNeeded()
|
||||
QProcess *process = new QProcess(this);
|
||||
process->setWorkingDirectory(QDir::tempPath());
|
||||
process->start("/usr/bin/lzop", QStringList() << "-o" << m_tempCoreName << "-x" << m_coreName);
|
||||
connect(process, SIGNAL(finished(int)), SLOT(continueAdapterStart()));
|
||||
connect(process, SIGNAL(finished(int)), SLOT(continueSetupEngine()));
|
||||
}
|
||||
|
||||
QString CoreGdbAdapter::coreFileName() const
|
||||
QString GdbCoreEngine::coreFileName() const
|
||||
{
|
||||
return m_tempCoreName.isEmpty() ? m_coreName : m_tempCoreName;
|
||||
}
|
||||
|
||||
@@ -33,7 +33,7 @@
|
||||
#ifndef DEBUGGER_COREGDBADAPTER_H
|
||||
#define DEBUGGER_COREGDBADAPTER_H
|
||||
|
||||
#include "abstractgdbadapter.h"
|
||||
#include "gdbengine.h"
|
||||
#include "localgdbprocess.h"
|
||||
|
||||
namespace Debugger {
|
||||
@@ -45,36 +45,32 @@ namespace Internal {
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
|
||||
class CoreGdbAdapter : public AbstractGdbAdapter
|
||||
class GdbCoreEngine : public GdbEngine
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit CoreGdbAdapter(GdbEngine *engine);
|
||||
~CoreGdbAdapter();
|
||||
GdbCoreEngine(const DebuggerStartParameters &startParameters,
|
||||
DebuggerEngine *masterEngine);
|
||||
~GdbCoreEngine();
|
||||
|
||||
private:
|
||||
DumperHandling dumperHandling() const { return DumperNotAvailable; }
|
||||
|
||||
void startAdapter();
|
||||
void handleGdbStartDone();
|
||||
void handleGdbStartFailed();
|
||||
void setupEngine();
|
||||
void setupInferior();
|
||||
void runEngine();
|
||||
void interruptInferior();
|
||||
void shutdownAdapter();
|
||||
|
||||
Q_SLOT void loadSymbolsForStack();
|
||||
Q_SLOT void loadAllSymbols();
|
||||
void shutdownEngine();
|
||||
|
||||
AbstractGdbProcess *gdbProc() { return &m_gdbProc; }
|
||||
|
||||
void handleFileExecAndSymbols(const GdbResponse &response);
|
||||
void handleTargetCore(const GdbResponse &response);
|
||||
void handleModulesList(const GdbResponse &response);
|
||||
void handleRoundTrip(const GdbResponse &response);
|
||||
void unpackCoreIfNeeded();
|
||||
QString coreFileName() const;
|
||||
Q_SLOT void continueAdapterStart();
|
||||
Q_SLOT void continueSetupEngine();
|
||||
QString coreName() const;
|
||||
|
||||
QString m_executable;
|
||||
|
||||
@@ -2,7 +2,6 @@ HEADERS += \
|
||||
$$PWD/gdbmi.h \
|
||||
$$PWD/gdbengine.h \
|
||||
$$PWD/gdboptionspage.h \
|
||||
$$PWD/abstractgdbadapter.h \
|
||||
$$PWD/attachgdbadapter.h \
|
||||
$$PWD/coregdbadapter.h \
|
||||
$$PWD/localplaingdbadapter.h \
|
||||
@@ -22,7 +21,6 @@ SOURCES += \
|
||||
$$PWD/classicgdbengine.cpp \
|
||||
$$PWD/pythongdbengine.cpp \
|
||||
$$PWD/gdboptionspage.cpp \
|
||||
$$PWD/abstractgdbadapter.cpp \
|
||||
$$PWD/attachgdbadapter.cpp \
|
||||
$$PWD/coregdbadapter.cpp \
|
||||
$$PWD/localplaingdbadapter.cpp \
|
||||
|
||||
@@ -69,6 +69,7 @@
|
||||
#include "debuggersourcepathmappingwidget.h"
|
||||
#include "hostutils.h"
|
||||
#include "logwindow.h"
|
||||
#include "procinterrupt.h"
|
||||
|
||||
#include <coreplugin/icore.h>
|
||||
#include <coreplugin/idocument.h>
|
||||
@@ -78,8 +79,9 @@
|
||||
#include <projectexplorer/taskhub.h>
|
||||
#include <projectexplorer/itaskhandler.h>
|
||||
#include <texteditor/itexteditor.h>
|
||||
#include <utils/qtcassert.h>
|
||||
#include <utils/elfreader.h>
|
||||
#include <utils/qtcassert.h>
|
||||
#include <utils/qtcprocess.h>
|
||||
|
||||
#include <QCoreApplication>
|
||||
#include <QDebug>
|
||||
@@ -243,7 +245,6 @@ GdbEngine::GdbEngine(const DebuggerStartParameters &startParameters,
|
||||
setObjectName(_("GdbEngine"));
|
||||
|
||||
m_busy = false;
|
||||
m_gdbAdapter = 0;
|
||||
m_debuggingHelperState = DebuggingHelperUninitialized;
|
||||
m_gdbVersion = 100;
|
||||
m_gdbBuildVersion = -1;
|
||||
@@ -268,8 +269,6 @@ GdbEngine::GdbEngine(const DebuggerStartParameters &startParameters,
|
||||
|
||||
invalidateSourcesList();
|
||||
|
||||
m_gdbAdapter = createAdapter();
|
||||
|
||||
m_debugInfoTaskHandler = new DebugInfoTaskHandler(this);
|
||||
ExtensionSystem::PluginManager::instance()->addObject(m_debugInfoTaskHandler);
|
||||
|
||||
@@ -280,16 +279,10 @@ GdbEngine::GdbEngine(const DebuggerStartParameters &startParameters,
|
||||
SLOT(reloadLocals()));
|
||||
connect(debuggerCore()->action(CreateFullBacktrace), SIGNAL(triggered()),
|
||||
SLOT(createFullBacktrace()));
|
||||
}
|
||||
|
||||
DebuggerStartMode GdbEngine::startMode() const
|
||||
{
|
||||
return startParameters().startMode;
|
||||
}
|
||||
|
||||
AbstractGdbProcess *GdbEngine::gdbProc() const
|
||||
{
|
||||
return m_gdbAdapter->gdbProc();
|
||||
connect(debuggerCore()->action(UseDebuggingHelpers), SIGNAL(valueChanged(QVariant)),
|
||||
SLOT(reloadLocals()));
|
||||
connect(debuggerCore()->action(UseDynamicType), SIGNAL(valueChanged(QVariant)),
|
||||
SLOT(reloadLocals()));
|
||||
}
|
||||
|
||||
GdbEngine::~GdbEngine()
|
||||
@@ -299,10 +292,12 @@ GdbEngine::~GdbEngine()
|
||||
m_debugInfoTaskHandler = 0;
|
||||
|
||||
// Prevent sending error messages afterwards.
|
||||
if (m_gdbAdapter)
|
||||
disconnect(gdbProc(), 0, this, 0);
|
||||
delete m_gdbAdapter;
|
||||
m_gdbAdapter = 0;
|
||||
disconnect();
|
||||
}
|
||||
|
||||
DebuggerStartMode GdbEngine::startMode() const
|
||||
{
|
||||
return startParameters().startMode;
|
||||
}
|
||||
|
||||
QString GdbEngine::errorMessage(QProcess::ProcessError error)
|
||||
@@ -396,11 +391,9 @@ static bool contains(const QByteArray &message, const char *pattern, int size)
|
||||
const int pos = message.indexOf(pattern);
|
||||
if (pos == -1)
|
||||
return false;
|
||||
if (pos != 0 && message.at(pos - 1) != '\n')
|
||||
return false;
|
||||
if (pos + size != s && message.at(pos + size + 1) != '\n')
|
||||
return false;
|
||||
return true;
|
||||
const bool beginFits = pos == 0 || message.at(pos - 1) == '\n';
|
||||
const bool endFits = pos + size == s || message.at(pos + size) == '\n';
|
||||
return beginFits && endFits;
|
||||
}
|
||||
|
||||
static bool isGdbConnectionError(const QByteArray &message)
|
||||
@@ -856,7 +849,7 @@ void GdbEngine::interruptInferior()
|
||||
} else {
|
||||
showStatusMessage(tr("Stop requested..."), 5000);
|
||||
showMessage(_("TRYING TO INTERRUPT INFERIOR"));
|
||||
m_gdbAdapter->interruptInferior();
|
||||
interruptInferior2();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -885,25 +878,6 @@ void GdbEngine::maybeHandleInferiorPidChanged(const QString &pid0)
|
||||
notifyInferiorPid(pid);
|
||||
}
|
||||
|
||||
void GdbEngine::postCommand(const QByteArray &command, AdapterCallback callback,
|
||||
const char *callbackName, const QVariant &cookie)
|
||||
{
|
||||
postCommand(command, NoFlags, callback, callbackName, cookie);
|
||||
}
|
||||
|
||||
void GdbEngine::postCommand(const QByteArray &command, GdbCommandFlags flags,
|
||||
AdapterCallback callback,
|
||||
const char *callbackName, const QVariant &cookie)
|
||||
{
|
||||
GdbCommand cmd;
|
||||
cmd.command = command;
|
||||
cmd.flags = flags;
|
||||
cmd.adapterCallback = callback;
|
||||
cmd.callbackName = callbackName;
|
||||
cmd.cookie = cookie;
|
||||
postCommandHelper(cmd);
|
||||
}
|
||||
|
||||
void GdbEngine::postCommand(const QByteArray &command, GdbCommandCallback callback,
|
||||
const char *callbackName, const QVariant &cookie)
|
||||
{
|
||||
@@ -1021,7 +995,7 @@ void GdbEngine::flushCommand(const GdbCommand &cmd0)
|
||||
QMetaObject::invokeMethod(this, "handleResponse",
|
||||
Q_ARG(QByteArray, buffer));
|
||||
} else {
|
||||
m_gdbAdapter->write(cmd.command + "\r\n");
|
||||
write(cmd.command + "\r\n");
|
||||
|
||||
// Start Watchdog.
|
||||
if (m_commandTimer.interval() <= 20000)
|
||||
@@ -1226,8 +1200,6 @@ void GdbEngine::handleResultRecord(GdbResponse *response)
|
||||
|
||||
if (cmd.callback)
|
||||
(this->*cmd.callback)(*response);
|
||||
else if (cmd.adapterCallback)
|
||||
(m_gdbAdapter->*cmd.adapterCallback)(*response);
|
||||
|
||||
if (cmd.flags & RebuildBreakpointModel) {
|
||||
--m_pendingBreakpointRequests;
|
||||
@@ -1595,7 +1567,7 @@ void GdbEngine::handleStop1(const GdbMi &data)
|
||||
// Don't load helpers on stops triggered by signals unless it's
|
||||
// an intentional trap.
|
||||
if (initHelpers
|
||||
&& m_gdbAdapter->dumperHandling() != AbstractGdbAdapter::DumperLoadedByGdbPreload
|
||||
&& dumperHandling() != DumperLoadedByGdbPreload
|
||||
&& reason == "signal-received") {
|
||||
const QByteArray name = data.findChild("signal-name").data();
|
||||
const DebuggerStartParameters &sp = startParameters();
|
||||
@@ -1775,8 +1747,8 @@ void GdbEngine::handleStop2()
|
||||
reloadStack(false); // Will trigger register reload.
|
||||
|
||||
if (supportsThreads()) {
|
||||
if (m_gdbAdapter->isCodaAdapter()) {
|
||||
m_gdbAdapter->codaReloadThreads();
|
||||
if (isCodaAdapter()) {
|
||||
codaReloadThreads();
|
||||
} else if (m_isMacGdb || m_gdbVersion < 70100) {
|
||||
postCommand("-thread-list-ids", Discardable, CB(handleThreadListIds));
|
||||
} else {
|
||||
@@ -1875,8 +1847,7 @@ void GdbEngine::pythonDumpersFailed()
|
||||
{
|
||||
m_hasPython = false;
|
||||
const DebuggerStartParameters &sp = startParameters();
|
||||
if (m_gdbAdapter->dumperHandling() == AbstractGdbAdapter::DumperLoadedByGdbPreload
|
||||
&& checkDebuggingHelpersClassic()) {
|
||||
if (dumperHandling() == DumperLoadedByGdbPreload && checkDebuggingHelpersClassic()) {
|
||||
QByteArray cmd = "set environment ";
|
||||
if (sp.toolChainAbi.os() == Abi::MacOS)
|
||||
cmd += "DYLD_INSERT_LIBRARIES";
|
||||
@@ -2031,15 +2002,10 @@ void GdbEngine::handleInferiorShutdown(const GdbResponse &response)
|
||||
}
|
||||
showMessageBox(QMessageBox::Critical,
|
||||
tr("Failed to shut down application"),
|
||||
AbstractGdbAdapter::msgInferiorStopFailed(QString::fromLocal8Bit(ba)));
|
||||
msgInferiorStopFailed(QString::fromLocal8Bit(ba)));
|
||||
notifyInferiorShutdownFailed();
|
||||
}
|
||||
|
||||
void GdbEngine::shutdownEngine()
|
||||
{
|
||||
m_gdbAdapter->shutdownAdapter();
|
||||
}
|
||||
|
||||
void GdbEngine::notifyAdapterShutdownFailed()
|
||||
{
|
||||
showMessage(_("ADAPTER SHUTDOWN FAILED"));
|
||||
@@ -2076,7 +2042,7 @@ void GdbEngine::handleGdbExit(const GdbResponse &response)
|
||||
// Don't set state here, this will be handled in handleGdbFinished()
|
||||
//notifyEngineShutdownOk();
|
||||
} else {
|
||||
QString msg = m_gdbAdapter->msgGdbStopFailed(
|
||||
QString msg = msgGdbStopFailed(
|
||||
QString::fromLocal8Bit(response.data.findChild("msg").data()));
|
||||
qDebug() << (_("GDB WON'T EXIT (%1); KILLING IT").arg(msg));
|
||||
showMessage(_("GDB WON'T EXIT (%1); KILLING IT").arg(msg));
|
||||
@@ -2121,50 +2087,6 @@ QString msgNoGdbBinaryForToolChain(const Abi &tc)
|
||||
.arg(tc.toString());
|
||||
}
|
||||
|
||||
AbstractGdbAdapter *GdbEngine::createAdapter()
|
||||
{
|
||||
const DebuggerStartParameters &sp = startParameters();
|
||||
if (sp.toolChainAbi.os() == Abi::SymbianOS) {
|
||||
// FIXME: 1 of 3 testing hacks.
|
||||
return new CodaGdbAdapter(this);
|
||||
}
|
||||
|
||||
switch (sp.startMode) {
|
||||
case AttachCore:
|
||||
return new CoreGdbAdapter(this);
|
||||
case AttachToRemoteServer:
|
||||
return new RemoteGdbServerAdapter(this);
|
||||
case StartRemoteGdb:
|
||||
return new RemotePlainGdbAdapter(this);
|
||||
case AttachExternal:
|
||||
return new AttachGdbAdapter(this);
|
||||
default:
|
||||
if (sp.useTerminal)
|
||||
return new TermGdbAdapter(this);
|
||||
return new LocalPlainGdbAdapter(this);
|
||||
}
|
||||
}
|
||||
|
||||
void GdbEngine::setupEngine()
|
||||
{
|
||||
QTC_ASSERT(state() == EngineSetupRequested, qDebug() << state());
|
||||
QTC_CHECK(m_debuggingHelperState == DebuggingHelperUninitialized);
|
||||
|
||||
if (m_gdbAdapter->dumperHandling() != AbstractGdbAdapter::DumperNotAvailable) {
|
||||
connect(debuggerCore()->action(UseDebuggingHelpers),
|
||||
SIGNAL(valueChanged(QVariant)),
|
||||
SLOT(reloadLocals()));
|
||||
connect(debuggerCore()->action(UseDynamicType),
|
||||
SIGNAL(valueChanged(QVariant)),
|
||||
SLOT(reloadLocals()));
|
||||
}
|
||||
|
||||
QTC_CHECK(state() == EngineSetupRequested);
|
||||
if (debuggerCore()->boolSetting(WarnOnReleaseBuilds))
|
||||
checkForReleaseBuild();
|
||||
m_gdbAdapter->startAdapter();
|
||||
}
|
||||
|
||||
bool GdbEngine::hasCapability(unsigned cap) const
|
||||
{
|
||||
if (cap & (ReverseSteppingCapability
|
||||
@@ -2237,7 +2159,7 @@ void GdbEngine::executeStep()
|
||||
setTokenBarrier();
|
||||
notifyInferiorRunRequested();
|
||||
showStatusMessage(tr("Step requested..."), 5000);
|
||||
if (m_gdbAdapter->isCodaAdapter() && stackHandler()->stackSize() > 0)
|
||||
if (isCodaAdapter() && stackHandler()->stackSize() > 0)
|
||||
postCommand("sal step,0x" + QByteArray::number(stackHandler()->topAddress(), 16));
|
||||
if (isReverseDebugging()) {
|
||||
postCommand("reverse-step", RunRequest, CB(handleExecuteStep));
|
||||
@@ -2311,7 +2233,7 @@ void GdbEngine::executeNext()
|
||||
setTokenBarrier();
|
||||
notifyInferiorRunRequested();
|
||||
showStatusMessage(tr("Step next requested..."), 5000);
|
||||
if (m_gdbAdapter->isCodaAdapter() && stackHandler()->stackSize() > 0)
|
||||
if (isCodaAdapter() && stackHandler()->stackSize() > 0)
|
||||
postCommand("sal next,0x" + QByteArray::number(stackHandler()->topAddress(), 16));
|
||||
if (isReverseDebugging()) {
|
||||
postCommand("reverse-next", RunRequest, CB(handleExecuteNext));
|
||||
@@ -3206,7 +3128,7 @@ void GdbEngine::insertBreakpoint(BreakpointModelId id)
|
||||
cmd = "-break-insert -a -f ";
|
||||
} else if (m_isMacGdb) {
|
||||
cmd = "-break-insert -l -1 -f ";
|
||||
} else if (m_gdbAdapter->isCodaAdapter()) {
|
||||
} else if (isCodaAdapter()) {
|
||||
cmd = "-break-insert -h -f ";
|
||||
} else if (m_gdbVersion >= 70000) {
|
||||
int spec = handler->threadSpec(id);
|
||||
@@ -3591,7 +3513,7 @@ void GdbEngine::reloadStack(bool forceGotoLocation)
|
||||
PENDING_DEBUG("RELOAD STACK");
|
||||
QByteArray cmd = "-stack-list-frames";
|
||||
int stackDepth = debuggerCore()->action(MaximalStackDepth)->value().toInt();
|
||||
if (stackDepth && !m_gdbAdapter->isCodaAdapter())
|
||||
if (stackDepth && !isCodaAdapter())
|
||||
cmd += " 0 " + QByteArray::number(stackDepth);
|
||||
postCommand(cmd, Discardable, CB(handleStackListFrames),
|
||||
QVariant::fromValue<StackCookie>(StackCookie(false, forceGotoLocation)));
|
||||
@@ -3832,12 +3754,12 @@ void GdbEngine::reloadRegisters()
|
||||
postCommand("-data-list-register-names", CB(handleRegisterListNames));
|
||||
m_registerNamesListed = true;
|
||||
// FIXME: Maybe better completely re-do this logic in CODA adapter.
|
||||
if (m_gdbAdapter->isCodaAdapter())
|
||||
if (isCodaAdapter())
|
||||
return;
|
||||
}
|
||||
|
||||
if (m_gdbAdapter->isCodaAdapter()) {
|
||||
m_gdbAdapter->codaReloadRegisters();
|
||||
if (isCodaAdapter()) {
|
||||
codaReloadRegisters();
|
||||
} else {
|
||||
postCommand("-data-list-register-values r",
|
||||
Discardable, CB(handleRegisterListValues));
|
||||
@@ -3865,8 +3787,8 @@ void GdbEngine::handleRegisterListNames(const GdbResponse &response)
|
||||
|
||||
registerHandler()->setRegisters(registers);
|
||||
|
||||
if (m_gdbAdapter->isCodaAdapter())
|
||||
m_gdbAdapter->codaReloadRegisters();
|
||||
if (isCodaAdapter())
|
||||
codaReloadRegisters();
|
||||
}
|
||||
|
||||
void GdbEngine::handleRegisterListValues(const GdbResponse &response)
|
||||
@@ -4047,7 +3969,7 @@ bool GdbEngine::hasDebuggingHelperForType(const QByteArray &type) const
|
||||
if (!debuggerCore()->boolSetting(UseDebuggingHelpers))
|
||||
return false;
|
||||
|
||||
if (m_gdbAdapter->dumperHandling() == AbstractGdbAdapter::DumperNotAvailable) {
|
||||
if (dumperHandling() == DumperNotAvailable) {
|
||||
// Inferior calls are not possible in gdb when looking at core files.
|
||||
return type == "QString" || type.endsWith("::QString")
|
||||
|| type == "QStringList" || type.endsWith("::QStringList");
|
||||
@@ -4760,7 +4682,7 @@ void GdbEngine::startGdb(const QStringList &args)
|
||||
const DebuggerStartParameters &sp = startParameters();
|
||||
m_gdb = gdbBinary(sp);
|
||||
if (m_gdb.isEmpty()) {
|
||||
m_gdbAdapter->handleGdbStartFailed();
|
||||
handleGdbStartFailed();
|
||||
handleAdapterStartFailed(
|
||||
msgNoGdbBinaryForToolChain(sp.toolChainAbi),
|
||||
_(Constants::DEBUGGER_COMMON_SETTINGS_ID));
|
||||
@@ -4786,7 +4708,7 @@ void GdbEngine::startGdb(const QStringList &args)
|
||||
gdbProc()->start(m_gdb, gdbArgs);
|
||||
|
||||
if (!gdbProc()->waitForStarted()) {
|
||||
m_gdbAdapter->handleGdbStartFailed();
|
||||
handleGdbStartFailed();
|
||||
const QString msg = errorMessage(QProcess::FailedToStart);
|
||||
handleAdapterStartFailed(msg);
|
||||
return;
|
||||
@@ -4866,6 +4788,47 @@ void GdbEngine::startGdb(const QStringList &args)
|
||||
"AN ERROR IS EXPECTED."));
|
||||
postCommand("disassemble 0 0", ConsoleCommand, CB(handleDisassemblerCheck));
|
||||
|
||||
typedef GlobalDebuggerOptions::SourcePathMap SourcePathMap;
|
||||
typedef SourcePathMap::const_iterator SourcePathMapIterator;
|
||||
|
||||
if (debuggerCore()->boolSetting(WarnOnReleaseBuilds))
|
||||
checkForReleaseBuild();
|
||||
|
||||
showStatusMessage(tr("Setting up inferior..."));
|
||||
|
||||
// Addint executable to modules list.
|
||||
Module module;
|
||||
module.startAddress = 0;
|
||||
module.endAddress = 0;
|
||||
module.modulePath = sp.executable;
|
||||
module.moduleName = QLatin1String("<executable>");
|
||||
modulesHandler()->updateModule(module);
|
||||
|
||||
// Apply source path mappings from global options.
|
||||
const SourcePathMap sourcePathMap =
|
||||
DebuggerSourcePathMappingWidget::mergePlatformQtPath(sp.qtInstallPath,
|
||||
debuggerCore()->globalDebuggerOptions()->sourcePathMap);
|
||||
const SourcePathMapIterator cend = sourcePathMap.constEnd();
|
||||
SourcePathMapIterator it = sourcePathMap.constBegin();
|
||||
for ( ; it != cend; ++it)
|
||||
postCommand("set substitute-path " + it.key().toLocal8Bit()
|
||||
+ " " + it.value().toLocal8Bit());
|
||||
|
||||
// Spaces just will not work.
|
||||
foreach (const QString &src, sp.debugSourceLocation)
|
||||
postCommand("directory " + src.toLocal8Bit());
|
||||
|
||||
const QByteArray sysroot = sp.sysroot.toLocal8Bit();
|
||||
if (!sysroot.isEmpty()) {
|
||||
postCommand("set sysroot " + sysroot);
|
||||
// sysroot is not enough to correctly locate the sources, so explicitly
|
||||
// relocate the most likely place for the debug source
|
||||
postCommand("set substitute-path /usr/src " + sysroot + "/usr/src");
|
||||
}
|
||||
|
||||
//QByteArray ba = QFileInfo(sp.dumperLibrary).path().toLocal8Bit();
|
||||
//if (!ba.isEmpty())
|
||||
// postCommand("set solib-search-path " + ba);
|
||||
if (attemptQuickStart()) {
|
||||
postCommand("set auto-solib-add off", ConsoleCommand);
|
||||
} else {
|
||||
@@ -4875,15 +4838,22 @@ void GdbEngine::startGdb(const QStringList &args)
|
||||
}
|
||||
|
||||
// Dummy command to guarantee a roundtrip before the adapter proceed.
|
||||
postCommand("pwd", ConsoleCommand, CB(handleGdbStart));
|
||||
postCommand("pwd", ConsoleCommand, CB(reportEngineSetupOk));
|
||||
}
|
||||
|
||||
void GdbEngine::handleGdbStart(const GdbResponse &response)
|
||||
void GdbEngine::reportEngineSetupOk(const GdbResponse &response)
|
||||
{
|
||||
Q_UNUSED(response);
|
||||
m_gdbAdapter->handleGdbStartDone();
|
||||
QTC_ASSERT(state() == EngineSetupRequested, qDebug() << state());
|
||||
showMessage(_("ENGINE SUCCESSFULLY STARTED"));
|
||||
notifyEngineSetupOk();
|
||||
}
|
||||
|
||||
void GdbEngine::handleGdbStartFailed()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
void GdbEngine::loadInitScript()
|
||||
{
|
||||
const QString script = startParameters().overrideStartScript;
|
||||
@@ -4982,9 +4952,8 @@ void GdbEngine::abortDebugger()
|
||||
if (targetState() == DebuggerFinished) {
|
||||
// We already tried. Try harder.
|
||||
showMessage(_("ABORTING DEBUGGER. SECOND TIME."));
|
||||
QTC_ASSERT(m_gdbAdapter, return);
|
||||
QTC_ASSERT(m_gdbAdapter->gdbProc(), return);
|
||||
m_gdbAdapter->gdbProc()->kill();
|
||||
QTC_ASSERT(gdbProc(), return);
|
||||
gdbProc()->kill();
|
||||
} else {
|
||||
// Be friendly the first time. This will change targetState().
|
||||
showMessage(_("ABORTING DEBUGGER. FIRST TIME."));
|
||||
@@ -5009,50 +4978,6 @@ void GdbEngine::handleAdapterStartFailed(const QString &msg,
|
||||
notifyEngineSetupFailed();
|
||||
}
|
||||
|
||||
void GdbEngine::handleAdapterStarted()
|
||||
{
|
||||
QTC_ASSERT(state() == EngineSetupRequested, qDebug() << state());
|
||||
showMessage(_("ADAPTER SUCCESSFULLY STARTED"));
|
||||
notifyEngineSetupOk();
|
||||
|
||||
Module module;
|
||||
module.startAddress = 0;
|
||||
module.endAddress = 0;
|
||||
module.modulePath = startParameters().executable;
|
||||
module.moduleName = QLatin1String("<executable>");
|
||||
modulesHandler()->updateModule(module);
|
||||
}
|
||||
|
||||
void GdbEngine::setupInferior()
|
||||
{
|
||||
QTC_ASSERT(state() == InferiorSetupRequested, qDebug() << state());
|
||||
typedef GlobalDebuggerOptions::SourcePathMap SourcePathMap;
|
||||
typedef SourcePathMap::const_iterator SourcePathMapIterator;
|
||||
|
||||
showStatusMessage(tr("Setting up inferior..."));
|
||||
const DebuggerStartParameters &sp = startParameters();
|
||||
|
||||
// Apply source path mappings from global options.
|
||||
const SourcePathMap sourcePathMap =
|
||||
DebuggerSourcePathMappingWidget::mergePlatformQtPath(sp.qtInstallPath,
|
||||
debuggerCore()->globalDebuggerOptions()->sourcePathMap);
|
||||
const SourcePathMapIterator cend = sourcePathMap.constEnd();
|
||||
SourcePathMapIterator it = sourcePathMap.constBegin();
|
||||
for ( ; it != cend; ++it)
|
||||
postCommand("set substitute-path " + it.key().toLocal8Bit()
|
||||
+ " " + it.value().toLocal8Bit());
|
||||
|
||||
// Spaces just will not work.
|
||||
foreach (const QString &src, sp.debugSourceLocation)
|
||||
postCommand("directory " + src.toLocal8Bit());
|
||||
|
||||
//QByteArray ba = QFileInfo(sp.dumperLibrary).path().toLocal8Bit();
|
||||
//if (!ba.isEmpty())
|
||||
// postCommand("set solib-search-path " + ba);
|
||||
|
||||
m_gdbAdapter->setupInferior();
|
||||
}
|
||||
|
||||
void GdbEngine::notifyInferiorSetupFailed()
|
||||
{
|
||||
// FIXME: that's not enough to stop gdb from getting confused
|
||||
@@ -5172,12 +5097,6 @@ void GdbEngine::handleBreakOnQFatal(const GdbResponse &response)
|
||||
notifyInferiorSetupOk();
|
||||
}
|
||||
|
||||
void GdbEngine::runEngine()
|
||||
{
|
||||
QTC_ASSERT(state() == EngineRunRequested, qDebug() << state());
|
||||
m_gdbAdapter->runEngine();
|
||||
}
|
||||
|
||||
void GdbEngine::notifyInferiorSetupFailed(const QString &msg)
|
||||
{
|
||||
showStatusMessage(tr("Failed to start application: ") + msg);
|
||||
@@ -5246,14 +5165,15 @@ void GdbEngine::resetCommandQueue()
|
||||
|
||||
void GdbEngine::handleRemoteSetupDone(int gdbServerPort, int qmlPort)
|
||||
{
|
||||
Q_UNUSED(gdbServerPort);
|
||||
Q_UNUSED(qmlPort);
|
||||
notifyEngineRemoteSetupDone();
|
||||
m_gdbAdapter->handleRemoteSetupDone(gdbServerPort, qmlPort);
|
||||
}
|
||||
|
||||
void GdbEngine::handleRemoteSetupFailed(const QString &message)
|
||||
{
|
||||
Q_UNUSED(message);
|
||||
notifyEngineRemoteSetupFailed();
|
||||
m_gdbAdapter->handleRemoteSetupFailed(message);
|
||||
}
|
||||
|
||||
bool GdbEngine::setupQmlStep(bool on)
|
||||
@@ -5421,14 +5341,106 @@ void GdbEngine::checkForReleaseBuild()
|
||||
showMessageBox(QMessageBox::Information, tr("Warning"), warning);
|
||||
}
|
||||
|
||||
void GdbEngine::write(const QByteArray &data)
|
||||
{
|
||||
gdbProc()->write(data);
|
||||
}
|
||||
|
||||
bool GdbEngine::isCodaAdapter() const
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
bool GdbEngine::prepareCommand()
|
||||
{
|
||||
#ifdef Q_OS_WIN
|
||||
Utils::QtcProcess::SplitError perr;
|
||||
startParameters().processArgs = Utils::QtcProcess::prepareArgs(
|
||||
startParameters().processArgs, &perr,
|
||||
&startParameters().environment, &startParameters().workingDirectory);
|
||||
if (perr != Utils::QtcProcess::SplitOk) {
|
||||
// perr == BadQuoting is never returned on Windows
|
||||
// FIXME? QTCREATORBUG-2809
|
||||
handleAdapterStartFailed(QCoreApplication::translate("DebuggerEngine", // Same message in CdbEngine
|
||||
"Debugging complex command lines is currently not supported on Windows."), QString());
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
|
||||
QString GdbEngine::msgGdbStopFailed(const QString &why)
|
||||
{
|
||||
return tr("The gdb process could not be stopped:\n%1").arg(why);
|
||||
}
|
||||
|
||||
QString GdbEngine::msgInferiorStopFailed(const QString &why)
|
||||
{
|
||||
return tr("Application process could not be stopped:\n%1").arg(why);
|
||||
}
|
||||
|
||||
QString GdbEngine::msgInferiorSetupOk()
|
||||
{
|
||||
return tr("Application started");
|
||||
}
|
||||
|
||||
QString GdbEngine::msgInferiorRunOk()
|
||||
{
|
||||
return tr("Application running");
|
||||
}
|
||||
|
||||
QString GdbEngine::msgAttachedToStoppedInferior()
|
||||
{
|
||||
return tr("Attached to stopped application");
|
||||
}
|
||||
|
||||
QString GdbEngine::msgConnectRemoteServerFailed(const QString &why)
|
||||
{
|
||||
return tr("Connecting to remote server failed:\n%1").arg(why);
|
||||
}
|
||||
|
||||
void GdbEngine::interruptLocalInferior(qint64 pid)
|
||||
{
|
||||
QTC_ASSERT(state() == InferiorStopRequested, qDebug() << state(); return);
|
||||
if (pid <= 0) {
|
||||
showMessage(QLatin1String("TRYING TO INTERRUPT INFERIOR BEFORE PID WAS OBTAINED"), LogError);
|
||||
return;
|
||||
}
|
||||
QString errorMessage;
|
||||
if (interruptProcess(pid, GdbEngineType, &errorMessage)) {
|
||||
showMessage(QLatin1String("Interrupted ") + QString::number(pid));
|
||||
} else {
|
||||
showMessage(errorMessage, LogError);
|
||||
notifyInferiorStopFailed();
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Factory
|
||||
//
|
||||
|
||||
DebuggerEngine *createGdbEngine(const DebuggerStartParameters &startParameters,
|
||||
DebuggerEngine *createGdbEngine(const DebuggerStartParameters &sp,
|
||||
DebuggerEngine *masterEngine)
|
||||
{
|
||||
return new GdbEngine(startParameters, masterEngine);
|
||||
if (sp.toolChainAbi.os() == Abi::SymbianOS) {
|
||||
// FIXME: 1 of 3 testing hacks.
|
||||
return new GdbCodaEngine(sp, masterEngine);
|
||||
}
|
||||
|
||||
switch (sp.startMode) {
|
||||
case AttachCore:
|
||||
return new GdbCoreEngine(sp, masterEngine);
|
||||
case AttachToRemoteServer:
|
||||
return new GdbRemoteServerEngine(sp, masterEngine);
|
||||
case StartRemoteGdb:
|
||||
return new GdbRemotePlainEngine(sp, masterEngine);
|
||||
case AttachExternal:
|
||||
return new GdbAttachEngine(sp, masterEngine);
|
||||
default:
|
||||
if (sp.useTerminal)
|
||||
return new GdbTermEngine(sp, masterEngine);
|
||||
return new GdbLocalPlainEngine(sp, masterEngine);
|
||||
}
|
||||
}
|
||||
|
||||
void addGdbOptionPages(QList<Core::IOptionsPage *> *opts)
|
||||
|
||||
@@ -56,24 +56,17 @@
|
||||
namespace Debugger {
|
||||
namespace Internal {
|
||||
|
||||
class AbstractGdbAdapter;
|
||||
class AbstractGdbProcess;
|
||||
class DebugInfoTask;
|
||||
class DebugInfoTaskHandler;
|
||||
class GdbResponse;
|
||||
class GdbMi;
|
||||
class GdbToolTipContext;
|
||||
class Module;
|
||||
|
||||
class WatchData;
|
||||
class DisassemblerAgentCookie;
|
||||
class DisassemblerLines;
|
||||
|
||||
class AttachGdbAdapter;
|
||||
class CoreGdbAdapter;
|
||||
class LocalPlainGdbAdapter;
|
||||
class RemoteGdbServerAdapter;
|
||||
|
||||
enum DebuggingHelperState
|
||||
{
|
||||
DebuggingHelperUninitialized,
|
||||
@@ -207,30 +200,18 @@ public:
|
||||
GdbEngine(const DebuggerStartParameters &startParameters,
|
||||
DebuggerEngine *masterEngine);
|
||||
~GdbEngine();
|
||||
AbstractGdbAdapter *gdbAdapter() const { return m_gdbAdapter; }
|
||||
|
||||
private:
|
||||
friend class AbstractGdbAdapter;
|
||||
friend class AbstractPlainGdbAdapter;
|
||||
friend class AttachGdbAdapter;
|
||||
friend class CoreGdbAdapter;
|
||||
friend class LocalPlainGdbAdapter;
|
||||
friend class TermGdbAdapter;
|
||||
friend class RemoteGdbServerAdapter;
|
||||
friend class RemotePlainGdbAdapter;
|
||||
friend class CodaGdbAdapter;
|
||||
|
||||
private: ////////// General Interface //////////
|
||||
|
||||
virtual void setupEngine();
|
||||
virtual void setupInferior();
|
||||
virtual void runEngine();
|
||||
virtual void setupEngine() = 0;
|
||||
virtual void handleGdbStartFailed();
|
||||
virtual void setupInferior() = 0;
|
||||
virtual void notifyInferiorSetupFailed();
|
||||
|
||||
virtual bool hasCapability(unsigned) const;
|
||||
virtual void detachDebugger();
|
||||
virtual void shutdownEngine();
|
||||
virtual void shutdownInferior();
|
||||
virtual void notifyInferiorSetupFailed();
|
||||
virtual void shutdownEngine() = 0;
|
||||
virtual void abortDebugger();
|
||||
|
||||
virtual bool acceptsDebuggerCommands() const;
|
||||
@@ -246,18 +227,16 @@ private: ////////// General State //////////
|
||||
|
||||
bool m_registerNamesListed;
|
||||
|
||||
private: ////////// Gdb Process Management //////////
|
||||
protected: ////////// Gdb Process Management //////////
|
||||
|
||||
AbstractGdbAdapter *createAdapter();
|
||||
void startGdb(const QStringList &args = QStringList());
|
||||
void handleGdbStart(const GdbResponse &response);
|
||||
void reportEngineSetupOk(const GdbResponse &response);
|
||||
void handleInferiorShutdown(const GdbResponse &response);
|
||||
void handleGdbExit(const GdbResponse &response);
|
||||
void handleRemoteSetupDone(int gdbServerPort, int qmlPort);
|
||||
void handleRemoteSetupFailed(const QString &message);
|
||||
void handleNamespaceExtraction(const GdbResponse &response);
|
||||
|
||||
void handleAdapterStarted();
|
||||
void loadInitScript();
|
||||
void loadPythonDumpers();
|
||||
void pythonDumpersFailed();
|
||||
@@ -299,8 +278,6 @@ private:
|
||||
QByteArray m_inbuffer;
|
||||
bool m_busy;
|
||||
|
||||
AbstractGdbAdapter *m_gdbAdapter;
|
||||
|
||||
// Name of the convenience variable containing the last
|
||||
// known function return value.
|
||||
QByteArray m_resultVarName;
|
||||
@@ -330,22 +307,18 @@ private: ////////// Gdb Command Management //////////
|
||||
ConsoleCommand = 512
|
||||
};
|
||||
Q_DECLARE_FLAGS(GdbCommandFlags, GdbCommandFlag)
|
||||
private:
|
||||
|
||||
typedef void (GdbEngine::*GdbCommandCallback)
|
||||
(const GdbResponse &response);
|
||||
typedef void (AbstractGdbAdapter::*AdapterCallback)
|
||||
(const GdbResponse &response);
|
||||
protected:
|
||||
typedef void (GdbEngine::*GdbCommandCallback)(const GdbResponse &response);
|
||||
|
||||
struct GdbCommand
|
||||
{
|
||||
GdbCommand()
|
||||
: flags(0), callback(0), adapterCallback(0), callbackName(0)
|
||||
: flags(0), callback(0), callbackName(0)
|
||||
{}
|
||||
|
||||
int flags;
|
||||
GdbCommandCallback callback;
|
||||
AdapterCallback adapterCallback;
|
||||
const char *callbackName;
|
||||
QByteArray command;
|
||||
QVariant cookie;
|
||||
@@ -357,6 +330,7 @@ private: ////////// Gdb Command Management //////////
|
||||
// send and decrements on receipt, effectively preventing
|
||||
// watch model updates before everything is finished.
|
||||
void flushCommand(const GdbCommand &cmd);
|
||||
protected:
|
||||
void postCommand(const QByteArray &command,
|
||||
GdbCommandFlags flags,
|
||||
GdbCommandCallback callback = 0,
|
||||
@@ -366,15 +340,7 @@ private: ////////// Gdb Command Management //////////
|
||||
GdbCommandCallback callback = 0,
|
||||
const char *callbackName = 0,
|
||||
const QVariant &cookie = QVariant());
|
||||
void postCommand(const QByteArray &command,
|
||||
AdapterCallback callback,
|
||||
const char *callbackName,
|
||||
const QVariant &cookie = QVariant());
|
||||
void postCommand(const QByteArray &command,
|
||||
GdbCommandFlags flags,
|
||||
AdapterCallback callback,
|
||||
const char *callbackName,
|
||||
const QVariant &cookie = QVariant());
|
||||
private:
|
||||
void postCommandHelper(const GdbCommand &cmd);
|
||||
void flushQueuedCommands();
|
||||
Q_SLOT void commandTimeout();
|
||||
@@ -407,7 +373,7 @@ private: ////////// Gdb Command Management //////////
|
||||
void checkForReleaseBuild();
|
||||
|
||||
private: ////////// Gdb Output, State & Capability Handling //////////
|
||||
|
||||
protected:
|
||||
Q_SLOT void handleResponse(const QByteArray &buff);
|
||||
void handleStopResponse(const GdbMi &data);
|
||||
void handleResultRecord(GdbResponse *response);
|
||||
@@ -451,11 +417,13 @@ private: ////////// Inferior Management //////////
|
||||
void executeStepI();
|
||||
void executeNextI();
|
||||
|
||||
protected:
|
||||
void continueInferiorInternal();
|
||||
void doNotifyInferiorRunOk();
|
||||
void autoContinueInferior();
|
||||
void continueInferior();
|
||||
void interruptInferior();
|
||||
virtual void interruptInferior2() {}
|
||||
void interruptInferiorTemporarily();
|
||||
|
||||
void executeRunToLine(const ContextData &data);
|
||||
@@ -474,6 +442,7 @@ private: ////////// Inferior Management //////////
|
||||
void handleInfoProc(const GdbResponse &response);
|
||||
|
||||
private: ////////// View & Data Stuff //////////
|
||||
protected:
|
||||
|
||||
void selectThread(int index);
|
||||
void activateFrame(int index);
|
||||
@@ -509,7 +478,7 @@ private: ////////// View & Data Stuff //////////
|
||||
// Modules specific stuff
|
||||
//
|
||||
void loadSymbols(const QString &moduleName);
|
||||
void loadAllSymbols();
|
||||
Q_SLOT void loadAllSymbols();
|
||||
void loadSymbolsForStack();
|
||||
void requestModuleSymbols(const QString &moduleName);
|
||||
void reloadModules();
|
||||
@@ -584,6 +553,7 @@ private: ////////// View & Data Stuff //////////
|
||||
//
|
||||
// Stack specific stuff
|
||||
//
|
||||
protected:
|
||||
void updateAll();
|
||||
void updateAllClassic();
|
||||
void updateAllPython();
|
||||
@@ -743,8 +713,39 @@ private: ////////// View & Data Stuff //////////
|
||||
bool m_forceAsyncModel;
|
||||
QList<WatchData> m_completed;
|
||||
QSet<QByteArray> m_uncompleted;
|
||||
|
||||
static QString msgGdbStopFailed(const QString &why);
|
||||
static QString msgInferiorStopFailed(const QString &why);
|
||||
static QString msgAttachedToStoppedInferior();
|
||||
static QString msgInferiorSetupOk();
|
||||
static QString msgInferiorRunOk();
|
||||
static QString msgConnectRemoteServerFailed(const QString &why);
|
||||
|
||||
protected:
|
||||
enum DumperHandling
|
||||
{
|
||||
DumperNotAvailable,
|
||||
DumperLoadedByAdapter,
|
||||
DumperLoadedByGdbPreload,
|
||||
DumperLoadedByGdb
|
||||
};
|
||||
|
||||
virtual void write(const QByteArray &data);
|
||||
|
||||
virtual AbstractGdbProcess *gdbProc() = 0;
|
||||
virtual DumperHandling dumperHandling() const = 0;
|
||||
|
||||
// CODA specific stuff
|
||||
virtual bool isCodaAdapter() const;
|
||||
virtual void codaReloadRegisters() {}
|
||||
virtual void codaReloadThreads() {}
|
||||
|
||||
protected:
|
||||
bool prepareCommand();
|
||||
void interruptLocalInferior(qint64 pid);
|
||||
};
|
||||
|
||||
|
||||
} // namespace Internal
|
||||
} // namespace Debugger
|
||||
|
||||
|
||||
@@ -53,15 +53,16 @@ namespace Internal {
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
|
||||
LocalPlainGdbAdapter::LocalPlainGdbAdapter(GdbEngine *engine)
|
||||
: AbstractPlainGdbAdapter(engine)
|
||||
GdbLocalPlainEngine::GdbLocalPlainEngine(const DebuggerStartParameters &startParameters,
|
||||
DebuggerEngine *masterEngine)
|
||||
: GdbAbstractPlainEngine(startParameters, masterEngine)
|
||||
{
|
||||
// Output
|
||||
connect(&m_outputCollector, SIGNAL(byteDelivery(QByteArray)),
|
||||
engine, SLOT(readDebugeeOutput(QByteArray)));
|
||||
this, SLOT(readDebugeeOutput(QByteArray)));
|
||||
}
|
||||
|
||||
AbstractGdbAdapter::DumperHandling LocalPlainGdbAdapter::dumperHandling() const
|
||||
GdbEngine::DumperHandling GdbLocalPlainEngine::dumperHandling() const
|
||||
{
|
||||
// LD_PRELOAD fails for System-Qt on Mac.
|
||||
#if defined(Q_OS_WIN) || defined(Q_OS_MAC)
|
||||
@@ -71,7 +72,7 @@ AbstractGdbAdapter::DumperHandling LocalPlainGdbAdapter::dumperHandling() const
|
||||
#endif
|
||||
}
|
||||
|
||||
void LocalPlainGdbAdapter::startAdapter()
|
||||
void GdbLocalPlainEngine::setupEngine()
|
||||
{
|
||||
QTC_ASSERT(state() == EngineSetupRequested, qDebug() << state());
|
||||
showMessage(_("TRYING TO START ADAPTER"));
|
||||
@@ -82,7 +83,7 @@ void LocalPlainGdbAdapter::startAdapter()
|
||||
QStringList gdbArgs;
|
||||
|
||||
if (!m_outputCollector.listen()) {
|
||||
m_engine->handleAdapterStartFailed(tr("Cannot set up communication with child process: %1")
|
||||
handleAdapterStartFailed(tr("Cannot set up communication with child process: %1")
|
||||
.arg(m_outputCollector.errorString()));
|
||||
return;
|
||||
}
|
||||
@@ -93,53 +94,38 @@ void LocalPlainGdbAdapter::startAdapter()
|
||||
if (startParameters().environment.size())
|
||||
m_gdbProc.setEnvironment(startParameters().environment.toStringList());
|
||||
|
||||
m_engine->startGdb(gdbArgs);
|
||||
startGdb(gdbArgs);
|
||||
}
|
||||
|
||||
void LocalPlainGdbAdapter::handleGdbStartDone()
|
||||
{
|
||||
m_engine->handleAdapterStarted();
|
||||
}
|
||||
|
||||
void LocalPlainGdbAdapter::handleGdbStartFailed()
|
||||
void GdbLocalPlainEngine::handleGdbStartFailed()
|
||||
{
|
||||
m_outputCollector.shutdown();
|
||||
}
|
||||
|
||||
void LocalPlainGdbAdapter::setupInferior()
|
||||
{
|
||||
AbstractPlainGdbAdapter::setupInferior();
|
||||
}
|
||||
|
||||
void LocalPlainGdbAdapter::runEngine()
|
||||
{
|
||||
AbstractPlainGdbAdapter::runEngine();
|
||||
}
|
||||
|
||||
void LocalPlainGdbAdapter::shutdownAdapter()
|
||||
void GdbLocalPlainEngine::shutdownEngine()
|
||||
{
|
||||
showMessage(_("PLAIN ADAPTER SHUTDOWN %1").arg(state()));
|
||||
m_outputCollector.shutdown();
|
||||
m_engine->notifyAdapterShutdownOk();
|
||||
notifyAdapterShutdownOk();
|
||||
}
|
||||
|
||||
void LocalPlainGdbAdapter::interruptInferior()
|
||||
void GdbLocalPlainEngine::interruptInferior2()
|
||||
{
|
||||
interruptLocalInferior(m_engine->inferiorPid());
|
||||
interruptLocalInferior(inferiorPid());
|
||||
}
|
||||
|
||||
QByteArray LocalPlainGdbAdapter::execFilePath() const
|
||||
QByteArray GdbLocalPlainEngine::execFilePath() const
|
||||
{
|
||||
return QFileInfo(startParameters().executable)
|
||||
.absoluteFilePath().toLocal8Bit();
|
||||
}
|
||||
|
||||
QByteArray LocalPlainGdbAdapter::toLocalEncoding(const QString &s) const
|
||||
QByteArray GdbLocalPlainEngine::toLocalEncoding(const QString &s) const
|
||||
{
|
||||
return s.toLocal8Bit();
|
||||
}
|
||||
|
||||
QString LocalPlainGdbAdapter::fromLocalEncoding(const QByteArray &b) const
|
||||
QString GdbLocalPlainEngine::fromLocalEncoding(const QByteArray &b) const
|
||||
{
|
||||
return QString::fromLocal8Bit(b);
|
||||
}
|
||||
|
||||
@@ -46,21 +46,19 @@ namespace Internal {
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
|
||||
class LocalPlainGdbAdapter : public AbstractPlainGdbAdapter
|
||||
class GdbLocalPlainEngine : public GdbAbstractPlainEngine
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit LocalPlainGdbAdapter(GdbEngine *engine);
|
||||
GdbLocalPlainEngine(const DebuggerStartParameters &startParameters,
|
||||
DebuggerEngine *masterEngine);
|
||||
|
||||
private:
|
||||
void startAdapter();
|
||||
void handleGdbStartDone();
|
||||
void setupEngine();
|
||||
void handleGdbStartFailed();
|
||||
void setupInferior();
|
||||
void runEngine();
|
||||
void interruptInferior();
|
||||
void shutdownAdapter();
|
||||
void interruptInferior2();
|
||||
void shutdownEngine();
|
||||
|
||||
DumperHandling dumperHandling() const;
|
||||
AbstractGdbProcess *gdbProc() { return &m_gdbProc; }
|
||||
|
||||
@@ -32,7 +32,6 @@
|
||||
|
||||
#include "gdbengine.h"
|
||||
#include "gdbmi.h"
|
||||
#include "abstractgdbadapter.h"
|
||||
#include "debuggeractions.h"
|
||||
#include "debuggercore.h"
|
||||
#include "debuggerstringutils.h"
|
||||
@@ -202,8 +201,8 @@ void GdbEngine::updateAllPython()
|
||||
postCommand("-stack-list-frames", CB(handleStackListFrames),
|
||||
QVariant::fromValue<StackCookie>(StackCookie(false, true)));
|
||||
stackHandler()->setCurrentIndex(0);
|
||||
if (m_gdbAdapter->isCodaAdapter())
|
||||
m_gdbAdapter->codaReloadThreads();
|
||||
if (isCodaAdapter())
|
||||
codaReloadThreads();
|
||||
else
|
||||
postCommand("-thread-info", CB(handleThreadInfo), 0);
|
||||
reloadRegisters();
|
||||
|
||||
@@ -49,7 +49,7 @@ namespace Debugger {
|
||||
namespace Internal {
|
||||
|
||||
RemoteGdbProcess::RemoteGdbProcess(const QSsh::SshConnectionParameters &connParams,
|
||||
RemotePlainGdbAdapter *adapter, QObject *parent)
|
||||
GdbRemotePlainEngine *adapter, QObject *parent)
|
||||
: AbstractGdbProcess(parent), m_connParams(connParams), m_conn(0),
|
||||
m_state(Inactive), m_adapter(adapter)
|
||||
{
|
||||
|
||||
@@ -44,14 +44,14 @@
|
||||
namespace Debugger {
|
||||
namespace Internal {
|
||||
|
||||
class RemotePlainGdbAdapter;
|
||||
class GdbRemotePlainEngine;
|
||||
|
||||
class RemoteGdbProcess : public AbstractGdbProcess
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
RemoteGdbProcess(const QSsh::SshConnectionParameters &server,
|
||||
RemotePlainGdbAdapter *adapter, QObject *parent = 0);
|
||||
GdbRemotePlainEngine *adapter, QObject *parent = 0);
|
||||
|
||||
virtual QByteArray readAllStandardOutput();
|
||||
virtual QByteArray readAllStandardError();
|
||||
@@ -123,7 +123,7 @@ private:
|
||||
QByteArray m_appOutputFileName;
|
||||
State m_state;
|
||||
|
||||
RemotePlainGdbAdapter *m_adapter;
|
||||
GdbRemotePlainEngine *m_adapter;
|
||||
};
|
||||
|
||||
} // namespace Internal
|
||||
|
||||
@@ -50,7 +50,7 @@ namespace Debugger {
|
||||
namespace Internal {
|
||||
|
||||
#define CB(callback) \
|
||||
static_cast<GdbEngine::AdapterCallback>(&RemoteGdbServerAdapter::callback), \
|
||||
static_cast<GdbEngine::GdbCommandCallback>(&GdbRemoteServerEngine::callback), \
|
||||
STRINGIFY(callback)
|
||||
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
@@ -59,8 +59,9 @@ namespace Internal {
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
|
||||
RemoteGdbServerAdapter::RemoteGdbServerAdapter(GdbEngine *engine)
|
||||
: AbstractGdbAdapter(engine)
|
||||
GdbRemoteServerEngine::GdbRemoteServerEngine(const DebuggerStartParameters &startParameters,
|
||||
DebuggerEngine *masterEngine)
|
||||
: GdbEngine(startParameters, masterEngine)
|
||||
{
|
||||
connect(&m_uploadProc, SIGNAL(error(QProcess::ProcessError)),
|
||||
SLOT(uploadProcError(QProcess::ProcessError)));
|
||||
@@ -72,7 +73,7 @@ RemoteGdbServerAdapter::RemoteGdbServerAdapter(GdbEngine *engine)
|
||||
SLOT(uploadProcFinished()));
|
||||
}
|
||||
|
||||
AbstractGdbAdapter::DumperHandling RemoteGdbServerAdapter::dumperHandling() const
|
||||
GdbEngine::DumperHandling GdbRemoteServerEngine::dumperHandling() const
|
||||
{
|
||||
using namespace ProjectExplorer;
|
||||
const Abi abi = startParameters().toolChainAbi;
|
||||
@@ -83,7 +84,7 @@ AbstractGdbAdapter::DumperHandling RemoteGdbServerAdapter::dumperHandling() cons
|
||||
return DumperLoadedByGdbPreload;
|
||||
}
|
||||
|
||||
void RemoteGdbServerAdapter::startAdapter()
|
||||
void GdbRemoteServerEngine::setupEngine()
|
||||
{
|
||||
QTC_ASSERT(state() == EngineSetupRequested, qDebug() << state());
|
||||
showMessage(_("TRYING TO START ADAPTER"));
|
||||
@@ -96,12 +97,12 @@ void RemoteGdbServerAdapter::startAdapter()
|
||||
}
|
||||
}
|
||||
if (startParameters().requestRemoteSetup)
|
||||
m_engine->notifyEngineRequestRemoteSetup();
|
||||
notifyEngineRequestRemoteSetup();
|
||||
else
|
||||
m_engine->startGdb();
|
||||
startGdb();
|
||||
}
|
||||
|
||||
void RemoteGdbServerAdapter::uploadProcError(QProcess::ProcessError error)
|
||||
void GdbRemoteServerEngine::uploadProcError(QProcess::ProcessError error)
|
||||
{
|
||||
QString msg;
|
||||
switch (error) {
|
||||
@@ -135,7 +136,7 @@ void RemoteGdbServerAdapter::uploadProcError(QProcess::ProcessError error)
|
||||
showMessageBox(QMessageBox::Critical, tr("Error"), msg);
|
||||
}
|
||||
|
||||
void RemoteGdbServerAdapter::readUploadStandardOutput()
|
||||
void GdbRemoteServerEngine::readUploadStandardOutput()
|
||||
{
|
||||
const QByteArray ba = m_uploadProc.readAllStandardOutput();
|
||||
const QString msg = QString::fromLocal8Bit(ba, ba.length());
|
||||
@@ -143,7 +144,7 @@ void RemoteGdbServerAdapter::readUploadStandardOutput()
|
||||
showMessage(msg, AppOutput);
|
||||
}
|
||||
|
||||
void RemoteGdbServerAdapter::readUploadStandardError()
|
||||
void GdbRemoteServerEngine::readUploadStandardError()
|
||||
{
|
||||
const QByteArray ba = m_uploadProc.readAllStandardError();
|
||||
const QString msg = QString::fromLocal8Bit(ba, ba.length());
|
||||
@@ -151,16 +152,16 @@ void RemoteGdbServerAdapter::readUploadStandardError()
|
||||
showMessage(msg, AppError);
|
||||
}
|
||||
|
||||
void RemoteGdbServerAdapter::uploadProcFinished()
|
||||
void GdbRemoteServerEngine::uploadProcFinished()
|
||||
{
|
||||
if (m_uploadProc.exitStatus() == QProcess::NormalExit
|
||||
&& m_uploadProc.exitCode() == 0)
|
||||
m_engine->startGdb();
|
||||
startGdb();
|
||||
else
|
||||
handleRemoteSetupFailed(m_uploadProc.errorString());
|
||||
}
|
||||
|
||||
void RemoteGdbServerAdapter::setupInferior()
|
||||
void GdbRemoteServerEngine::setupInferior()
|
||||
{
|
||||
QTC_ASSERT(state() == InferiorSetupRequested, qDebug() << state());
|
||||
const DebuggerStartParameters &sp = startParameters();
|
||||
@@ -174,28 +175,21 @@ void RemoteGdbServerAdapter::setupInferior()
|
||||
QFileInfo fi(sp.executable);
|
||||
fileName = fi.absoluteFilePath();
|
||||
}
|
||||
const QByteArray sysroot = sp.sysroot.toLocal8Bit();
|
||||
const QByteArray remoteArch = sp.remoteArchitecture.toLatin1();
|
||||
const QByteArray gnuTarget = sp.gnuTarget.toLatin1();
|
||||
const QByteArray searchPath = startParameters().searchPath.toLocal8Bit();
|
||||
//const QByteArray sysroot = sp.sysroot.toLocal8Bit();
|
||||
//const QByteArray remoteArch = sp.remoteArchitecture.toLatin1();
|
||||
//const QByteArray gnuTarget = sp.gnuTarget.toLatin1();
|
||||
const QString args = sp.processArgs;
|
||||
const QString solibSearchPath = startParameters().solibSearchPath.join(QLatin1String(PATHSEP));
|
||||
|
||||
if (!remoteArch.isEmpty())
|
||||
m_engine->postCommand("set architecture " + remoteArch);
|
||||
if (!gnuTarget.isEmpty())
|
||||
m_engine->postCommand("set gnutarget " + gnuTarget);
|
||||
if (!sysroot.isEmpty()) {
|
||||
m_engine->postCommand("set sysroot " + sysroot);
|
||||
// sysroot is not enough to correctly locate the sources, so explicitly
|
||||
// relocate the most likely place for the debug source
|
||||
m_engine->postCommand("set substitute-path /usr/src " + sysroot + "/usr/src");
|
||||
}
|
||||
// if (!remoteArch.isEmpty())
|
||||
// postCommand("set architecture " + remoteArch);
|
||||
// if (!gnuTarget.isEmpty())
|
||||
// postCommand("set gnutarget " + gnuTarget);
|
||||
const QString solibSearchPath = sp.solibSearchPath.join(QLatin1String(PATHSEP));
|
||||
if (!solibSearchPath.isEmpty())
|
||||
m_engine->postCommand("set solib-search-path " + solibSearchPath.toLocal8Bit());
|
||||
postCommand("set solib-search-path " + solibSearchPath.toLocal8Bit());
|
||||
|
||||
if (!args.isEmpty())
|
||||
m_engine->postCommand("-exec-arguments " + args.toLocal8Bit());
|
||||
postCommand("-exec-arguments " + args.toLocal8Bit());
|
||||
|
||||
// This has to be issued before 'target remote'. On pre-7.0 the
|
||||
// command is not present and will result in ' No symbol table is
|
||||
@@ -217,7 +211,7 @@ void RemoteGdbServerAdapter::setupInferior()
|
||||
// mi_execute_async_cli_command: Assertion `is_running (inferior_ptid)'
|
||||
// failed.\nA problem internal to GDB has been detected,[...]
|
||||
if (debuggerCore()->boolSetting(TargetAsync))
|
||||
m_engine->postCommand("set target-async on", CB(handleSetTargetAsync));
|
||||
postCommand("set target-async on", CB(handleSetTargetAsync));
|
||||
|
||||
if (fileName.isEmpty()) {
|
||||
showMessage(tr("No symbol file given."), StatusBar);
|
||||
@@ -225,19 +219,18 @@ void RemoteGdbServerAdapter::setupInferior()
|
||||
return;
|
||||
}
|
||||
|
||||
m_engine->postCommand("-file-exec-and-symbols \""
|
||||
+ fileName.toLocal8Bit() + '"',
|
||||
postCommand("-file-exec-and-symbols \"" + fileName.toLocal8Bit() + '"',
|
||||
CB(handleFileExecAndSymbols));
|
||||
}
|
||||
|
||||
void RemoteGdbServerAdapter::handleSetTargetAsync(const GdbResponse &response)
|
||||
void GdbRemoteServerEngine::handleSetTargetAsync(const GdbResponse &response)
|
||||
{
|
||||
QTC_ASSERT(state() == InferiorSetupRequested, qDebug() << state());
|
||||
if (response.resultClass == GdbResultError)
|
||||
qDebug() << "Adapter too old: does not support asynchronous mode.";
|
||||
}
|
||||
|
||||
void RemoteGdbServerAdapter::handleFileExecAndSymbols(const GdbResponse &response)
|
||||
void GdbRemoteServerEngine::handleFileExecAndSymbols(const GdbResponse &response)
|
||||
{
|
||||
QTC_ASSERT(state() == InferiorSetupRequested, qDebug() << state());
|
||||
if (response.resultClass == GdbResultDone) {
|
||||
@@ -251,12 +244,12 @@ void RemoteGdbServerAdapter::handleFileExecAndSymbols(const GdbResponse &respons
|
||||
showMessage(msg, StatusBar);
|
||||
callTargetRemote(); // Proceed nevertheless.
|
||||
} else {
|
||||
m_engine->notifyInferiorSetupFailed(msg);
|
||||
notifyInferiorSetupFailed(msg);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void RemoteGdbServerAdapter::callTargetRemote()
|
||||
void GdbRemoteServerEngine::callTargetRemote()
|
||||
{
|
||||
//m_breakHandler->clearBreakMarkers();
|
||||
|
||||
@@ -278,31 +271,31 @@ void RemoteGdbServerAdapter::callTargetRemote()
|
||||
channel = "tcp:" + channel;
|
||||
}
|
||||
|
||||
if (m_engine->m_isQnxGdb)
|
||||
m_engine->postCommand("target qnx " + channel, CB(handleTargetQnx));
|
||||
if (m_isQnxGdb)
|
||||
postCommand("target qnx " + channel, CB(handleTargetQnx));
|
||||
else
|
||||
m_engine->postCommand("target remote " + channel, CB(handleTargetRemote));
|
||||
postCommand("target remote " + channel, CB(handleTargetRemote));
|
||||
}
|
||||
|
||||
void RemoteGdbServerAdapter::handleTargetRemote(const GdbResponse &record)
|
||||
void GdbRemoteServerEngine::handleTargetRemote(const GdbResponse &record)
|
||||
{
|
||||
QTC_ASSERT(state() == InferiorSetupRequested, qDebug() << state());
|
||||
if (record.resultClass == GdbResultDone) {
|
||||
// gdb server will stop the remote application itself.
|
||||
showMessage(_("INFERIOR STARTED"));
|
||||
showMessage(msgAttachedToStoppedInferior(), StatusBar);
|
||||
m_engine->handleInferiorPrepared();
|
||||
handleInferiorPrepared();
|
||||
} else {
|
||||
// 16^error,msg="hd:5555: Connection timed out."
|
||||
QString msg = msgConnectRemoteServerFailed(
|
||||
QString::fromLocal8Bit(record.data.findChild("msg").data()));
|
||||
m_engine->notifyInferiorSetupFailed(msg);
|
||||
notifyInferiorSetupFailed(msg);
|
||||
}
|
||||
}
|
||||
|
||||
void RemoteGdbServerAdapter::handleTargetQnx(const GdbResponse &response)
|
||||
void GdbRemoteServerEngine::handleTargetQnx(const GdbResponse &response)
|
||||
{
|
||||
QTC_ASSERT(m_engine->m_isQnxGdb, qDebug() << m_engine->m_isQnxGdb);
|
||||
QTC_ASSERT(m_isQnxGdb, qDebug() << m_isQnxGdb);
|
||||
QTC_ASSERT(state() == InferiorSetupRequested, qDebug() << state());
|
||||
if (response.resultClass == GdbResultDone) {
|
||||
// gdb server will stop the remote application itself.
|
||||
@@ -311,19 +304,19 @@ void RemoteGdbServerAdapter::handleTargetQnx(const GdbResponse &response)
|
||||
|
||||
const qint64 pid = startParameters().attachPID;
|
||||
if (pid > -1) {
|
||||
m_engine->postCommand("attach " + QByteArray::number(pid), CB(handleAttach));
|
||||
postCommand("attach " + QByteArray::number(pid), CB(handleAttach));
|
||||
} else {
|
||||
m_engine->handleInferiorPrepared();
|
||||
handleInferiorPrepared();
|
||||
}
|
||||
} else {
|
||||
// 16^error,msg="hd:5555: Connection timed out."
|
||||
QString msg = msgConnectRemoteServerFailed(
|
||||
QString::fromLocal8Bit(response.data.findChild("msg").data()));
|
||||
m_engine->notifyInferiorSetupFailed(msg);
|
||||
notifyInferiorSetupFailed(msg);
|
||||
}
|
||||
}
|
||||
|
||||
void RemoteGdbServerAdapter::handleAttach(const GdbResponse &response)
|
||||
void GdbRemoteServerEngine::handleAttach(const GdbResponse &response)
|
||||
{
|
||||
QTC_ASSERT(state() == InferiorSetupRequested, qDebug() << state());
|
||||
switch (response.resultClass) {
|
||||
@@ -331,46 +324,46 @@ void RemoteGdbServerAdapter::handleAttach(const GdbResponse &response)
|
||||
case GdbResultRunning: {
|
||||
showMessage(_("INFERIOR ATTACHED"));
|
||||
showMessage(msgAttachedToStoppedInferior(), StatusBar);
|
||||
m_engine->handleInferiorPrepared();
|
||||
handleInferiorPrepared();
|
||||
break;
|
||||
}
|
||||
case GdbResultError:
|
||||
if (response.data.findChild("msg").data() == "ptrace: Operation not permitted.") {
|
||||
m_engine->notifyInferiorSetupFailed(DumperHelper::msgPtraceError(startParameters().startMode));
|
||||
notifyInferiorSetupFailed(DumperHelper::msgPtraceError(startParameters().startMode));
|
||||
break;
|
||||
}
|
||||
// if msg != "ptrace: ..." fall through
|
||||
default:
|
||||
QString msg = QString::fromLocal8Bit(response.data.findChild("msg").data());
|
||||
m_engine->notifyInferiorSetupFailed(msg);
|
||||
notifyInferiorSetupFailed(msg);
|
||||
}
|
||||
}
|
||||
|
||||
void RemoteGdbServerAdapter::runEngine()
|
||||
void GdbRemoteServerEngine::runEngine()
|
||||
{
|
||||
QTC_ASSERT(state() == EngineRunRequested, qDebug() << state());
|
||||
m_engine->notifyEngineRunAndInferiorStopOk();
|
||||
m_engine->continueInferiorInternal();
|
||||
notifyEngineRunAndInferiorStopOk();
|
||||
continueInferiorInternal();
|
||||
}
|
||||
|
||||
void RemoteGdbServerAdapter::interruptInferior()
|
||||
void GdbRemoteServerEngine::interruptInferior2()
|
||||
{
|
||||
QTC_ASSERT(state() == InferiorStopRequested, qDebug() << state());
|
||||
if (debuggerCore()->boolSetting(TargetAsync)) {
|
||||
m_engine->postCommand("-exec-interrupt", GdbEngine::Immediate,
|
||||
postCommand("-exec-interrupt", GdbEngine::Immediate,
|
||||
CB(handleInterruptInferior));
|
||||
} else {
|
||||
bool ok = m_gdbProc.interrupt();
|
||||
if (!ok) {
|
||||
// FIXME: Extra state needed?
|
||||
m_engine->showMessage(_("NOTE: INFERIOR STOP NOT POSSIBLE"));
|
||||
m_engine->showStatusMessage(tr("Interrupting not possible"));
|
||||
m_engine->notifyInferiorRunOk();
|
||||
showMessage(_("NOTE: INFERIOR STOP NOT POSSIBLE"));
|
||||
showStatusMessage(tr("Interrupting not possible"));
|
||||
notifyInferiorRunOk();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void RemoteGdbServerAdapter::handleInterruptInferior(const GdbResponse &response)
|
||||
void GdbRemoteServerEngine::handleInterruptInferior(const GdbResponse &response)
|
||||
{
|
||||
if (response.resultClass == GdbResultDone) {
|
||||
// The gdb server will trigger extra output that we will pick up
|
||||
@@ -378,17 +371,18 @@ void RemoteGdbServerAdapter::handleInterruptInferior(const GdbResponse &response
|
||||
} else {
|
||||
// FIXME: On some gdb versions like git 170ffa5d7dd this produces
|
||||
// >810^error,msg="mi_cmd_exec_interrupt: Inferior not executing."
|
||||
m_engine->notifyInferiorStopOk();
|
||||
notifyInferiorStopOk();
|
||||
}
|
||||
}
|
||||
|
||||
void RemoteGdbServerAdapter::shutdownAdapter()
|
||||
void GdbRemoteServerEngine::shutdownEngine()
|
||||
{
|
||||
m_engine->notifyAdapterShutdownOk();
|
||||
notifyAdapterShutdownOk();
|
||||
}
|
||||
|
||||
void RemoteGdbServerAdapter::handleRemoteSetupDone(int gdbServerPort, int qmlPort)
|
||||
void GdbRemoteServerEngine::handleRemoteSetupDone(int gdbServerPort, int qmlPort)
|
||||
{
|
||||
notifyEngineRemoteSetupDone();
|
||||
QTC_ASSERT(state() == EngineSetupRequested, qDebug() << state());
|
||||
|
||||
if (qmlPort != -1)
|
||||
@@ -401,23 +395,13 @@ void RemoteGdbServerAdapter::handleRemoteSetupDone(int gdbServerPort, int qmlPor
|
||||
QString::number(gdbServerPort));
|
||||
}
|
||||
}
|
||||
m_engine->startGdb();
|
||||
startGdb();
|
||||
}
|
||||
|
||||
void RemoteGdbServerAdapter::handleGdbStartDone()
|
||||
{
|
||||
m_engine->handleAdapterStarted();
|
||||
}
|
||||
|
||||
void RemoteGdbServerAdapter::handleGdbStartFailed()
|
||||
{
|
||||
}
|
||||
|
||||
void RemoteGdbServerAdapter::handleRemoteSetupFailed(const QString &reason)
|
||||
void GdbRemoteServerEngine::handleRemoteSetupFailed(const QString &reason)
|
||||
{
|
||||
QTC_ASSERT(state() == EngineSetupRequested, qDebug() << state());
|
||||
|
||||
m_engine->handleAdapterStartFailed(reason);
|
||||
handleAdapterStartFailed(reason);
|
||||
}
|
||||
|
||||
} // namespace Internal
|
||||
|
||||
@@ -33,7 +33,7 @@
|
||||
#ifndef DEBUGGER_REMOTEGDBADAPTER_H
|
||||
#define DEBUGGER_REMOTEGDBADAPTER_H
|
||||
|
||||
#include "abstractgdbadapter.h"
|
||||
#include "gdbengine.h"
|
||||
#include "localgdbprocess.h"
|
||||
|
||||
namespace Debugger {
|
||||
@@ -45,23 +45,22 @@ namespace Internal {
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
|
||||
class RemoteGdbServerAdapter : public AbstractGdbAdapter
|
||||
class GdbRemoteServerEngine : public GdbEngine
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
RemoteGdbServerAdapter(GdbEngine *engine);
|
||||
GdbRemoteServerEngine(const DebuggerStartParameters &startParameters,
|
||||
DebuggerEngine *masterEngine);
|
||||
|
||||
private:
|
||||
DumperHandling dumperHandling() const;
|
||||
|
||||
void startAdapter();
|
||||
void handleGdbStartDone();
|
||||
void handleGdbStartFailed();
|
||||
void setupEngine();
|
||||
void setupInferior();
|
||||
void runEngine();
|
||||
void interruptInferior();
|
||||
void shutdownAdapter();
|
||||
void interruptInferior2();
|
||||
void shutdownEngine();
|
||||
|
||||
AbstractGdbProcess *gdbProc() { return &m_gdbProc; }
|
||||
|
||||
|
||||
@@ -41,16 +41,17 @@
|
||||
namespace Debugger {
|
||||
namespace Internal {
|
||||
|
||||
RemotePlainGdbAdapter::RemotePlainGdbAdapter(GdbEngine *engine)
|
||||
: AbstractPlainGdbAdapter(engine),
|
||||
m_gdbProc(engine->startParameters().connParams, this)
|
||||
GdbRemotePlainEngine::GdbRemotePlainEngine(const DebuggerStartParameters &startParameters,
|
||||
DebuggerEngine *masterEngine)
|
||||
: GdbAbstractPlainEngine(startParameters, masterEngine),
|
||||
m_gdbProc(startParameters.connParams, this)
|
||||
{
|
||||
connect(&m_gdbProc, SIGNAL(started()), this, SLOT(handleGdbStarted()));
|
||||
connect(&m_gdbProc, SIGNAL(startFailed()), this,
|
||||
SLOT(handleGdbStartFailed1()));
|
||||
}
|
||||
|
||||
void RemotePlainGdbAdapter::startAdapter()
|
||||
void GdbRemotePlainEngine::setupEngine()
|
||||
{
|
||||
QTC_ASSERT(state() == EngineSetupRequested, qDebug() << state());
|
||||
showMessage(QLatin1String("TRYING TO START ADAPTER"));
|
||||
@@ -63,79 +64,68 @@ void RemotePlainGdbAdapter::startAdapter()
|
||||
handleRemoteSetupDone(startParameters().connParams.port, startParameters().qmlServerPort);
|
||||
}
|
||||
|
||||
void RemotePlainGdbAdapter::setupInferior()
|
||||
void GdbRemotePlainEngine::setupInferior()
|
||||
{
|
||||
AbstractPlainGdbAdapter::setupInferior();
|
||||
m_engine->postCommand("directory "
|
||||
+ m_engine->startParameters().remoteSourcesDir);
|
||||
GdbAbstractPlainEngine::setupInferior();
|
||||
postCommand("directory " + startParameters().remoteSourcesDir);
|
||||
}
|
||||
|
||||
void RemotePlainGdbAdapter::interruptInferior()
|
||||
void GdbRemotePlainEngine::interruptInferior2()
|
||||
{
|
||||
m_gdbProc.interruptInferior();
|
||||
}
|
||||
|
||||
QByteArray RemotePlainGdbAdapter::execFilePath() const
|
||||
QByteArray GdbRemotePlainEngine::execFilePath() const
|
||||
{
|
||||
return startParameters().executable.toUtf8();
|
||||
}
|
||||
|
||||
QByteArray RemotePlainGdbAdapter::toLocalEncoding(const QString &s) const
|
||||
QByteArray GdbRemotePlainEngine::toLocalEncoding(const QString &s) const
|
||||
{
|
||||
return s.toUtf8();
|
||||
}
|
||||
|
||||
QString RemotePlainGdbAdapter::fromLocalEncoding(const QByteArray &b) const
|
||||
QString GdbRemotePlainEngine::fromLocalEncoding(const QByteArray &b) const
|
||||
{
|
||||
return QString::fromUtf8(b);
|
||||
}
|
||||
|
||||
void RemotePlainGdbAdapter::handleApplicationOutput(const QByteArray &output)
|
||||
void GdbRemotePlainEngine::handleApplicationOutput(const QByteArray &output)
|
||||
{
|
||||
showMessage(QString::fromUtf8(output), AppOutput);
|
||||
}
|
||||
|
||||
void RemotePlainGdbAdapter::shutdownAdapter()
|
||||
void GdbRemotePlainEngine::shutdownEngine()
|
||||
{
|
||||
m_engine->notifyAdapterShutdownOk();
|
||||
notifyAdapterShutdownOk();
|
||||
}
|
||||
|
||||
void RemotePlainGdbAdapter::handleRemoteSetupDone(int gdbServerPort, int qmlPort)
|
||||
void GdbRemotePlainEngine::handleRemoteSetupDone(int gdbServerPort, int qmlPort)
|
||||
{
|
||||
Q_UNUSED(gdbServerPort);
|
||||
QTC_ASSERT(state() == EngineSetupRequested, qDebug() << state());
|
||||
|
||||
if (qmlPort != -1)
|
||||
startParameters().qmlServerPort = qmlPort;
|
||||
m_gdbProc.realStart(m_engine->startParameters().debuggerCommand,
|
||||
m_gdbProc.realStart(startParameters().debuggerCommand,
|
||||
QStringList() << QLatin1String("-i") << QLatin1String("mi"),
|
||||
m_engine->startParameters().executable);
|
||||
startParameters().executable);
|
||||
}
|
||||
|
||||
void RemotePlainGdbAdapter::handleGdbStarted()
|
||||
void GdbRemotePlainEngine::handleGdbStarted()
|
||||
{
|
||||
m_engine->startGdb();
|
||||
startGdb();
|
||||
}
|
||||
|
||||
void RemotePlainGdbAdapter::handleGdbStartDone()
|
||||
void GdbRemotePlainEngine::handleGdbStartFailed1()
|
||||
{
|
||||
m_engine->handleAdapterStarted();
|
||||
handleAdapterStartFailed(m_gdbProc.errorString());
|
||||
}
|
||||
|
||||
void RemotePlainGdbAdapter::handleGdbStartFailed()
|
||||
{
|
||||
}
|
||||
|
||||
void RemotePlainGdbAdapter::handleGdbStartFailed1()
|
||||
{
|
||||
m_engine->handleAdapterStartFailed(m_gdbProc.errorString());
|
||||
}
|
||||
|
||||
void RemotePlainGdbAdapter::handleRemoteSetupFailed(const QString &reason)
|
||||
void GdbRemotePlainEngine::handleRemoteSetupFailed(const QString &reason)
|
||||
{
|
||||
QTC_ASSERT(state() == EngineSetupRequested, qDebug() << state());
|
||||
|
||||
m_engine->handleAdapterStartFailed(reason);
|
||||
handleAdapterStartFailed(reason);
|
||||
}
|
||||
|
||||
} // namespace Internal
|
||||
|
||||
@@ -39,25 +39,24 @@
|
||||
namespace Debugger {
|
||||
namespace Internal {
|
||||
|
||||
class RemotePlainGdbAdapter : public AbstractPlainGdbAdapter
|
||||
class GdbRemotePlainEngine : public GdbAbstractPlainEngine
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
friend class RemoteGdbProcess;
|
||||
explicit RemotePlainGdbAdapter(GdbEngine *engine);
|
||||
GdbRemotePlainEngine(const DebuggerStartParameters &startParameters,
|
||||
DebuggerEngine *masterEngine);
|
||||
|
||||
private slots:
|
||||
void handleGdbStarted();
|
||||
void handleGdbStartFailed1();
|
||||
|
||||
private:
|
||||
void startAdapter();
|
||||
void handleGdbStartDone();
|
||||
void handleGdbStartFailed();
|
||||
void setupEngine();
|
||||
void setupInferior();
|
||||
void interruptInferior();
|
||||
void shutdownAdapter();
|
||||
void interruptInferior2();
|
||||
void shutdownEngine();
|
||||
void handleRemoteSetupDone(int gdbServerPort, int qmlPort);
|
||||
void handleRemoteSetupFailed(const QString &reason);
|
||||
AbstractGdbProcess *gdbProc() { return &m_gdbProc; }
|
||||
|
||||
@@ -49,7 +49,7 @@ namespace Debugger {
|
||||
namespace Internal {
|
||||
|
||||
#define CB(callback) \
|
||||
static_cast<GdbEngine::AdapterCallback>(&TermGdbAdapter::callback), \
|
||||
static_cast<GdbEngine::GdbCommandCallback>(&GdbTermEngine::callback), \
|
||||
STRINGIFY(callback)
|
||||
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
@@ -58,8 +58,9 @@ namespace Internal {
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
|
||||
TermGdbAdapter::TermGdbAdapter(GdbEngine *engine)
|
||||
: AbstractGdbAdapter(engine)
|
||||
GdbTermEngine::GdbTermEngine(const DebuggerStartParameters &startParameters,
|
||||
DebuggerEngine *masterEngine)
|
||||
: GdbEngine(startParameters, masterEngine)
|
||||
{
|
||||
#ifdef Q_OS_WIN
|
||||
// Windows up to xp needs a workaround for attaching to freshly started processes. see proc_stub_win
|
||||
@@ -72,18 +73,14 @@ TermGdbAdapter::TermGdbAdapter(GdbEngine *engine)
|
||||
m_stubProc.setMode(Utils::ConsoleProcess::Debug);
|
||||
m_stubProc.setSettings(Core::ICore::settings());
|
||||
#endif
|
||||
|
||||
connect(&m_stubProc, SIGNAL(processError(QString)), SLOT(stubError(QString)));
|
||||
connect(&m_stubProc, SIGNAL(processStarted()), SLOT(handleInferiorSetupOk()));
|
||||
connect(&m_stubProc, SIGNAL(wrapperStopped()), SLOT(stubExited()));
|
||||
}
|
||||
|
||||
TermGdbAdapter::~TermGdbAdapter()
|
||||
GdbTermEngine::~GdbTermEngine()
|
||||
{
|
||||
m_stubProc.disconnect(); // Avoid spurious state transitions from late exiting stub
|
||||
}
|
||||
|
||||
AbstractGdbAdapter::DumperHandling TermGdbAdapter::dumperHandling() const
|
||||
GdbEngine::DumperHandling GdbTermEngine::dumperHandling() const
|
||||
{
|
||||
// LD_PRELOAD fails for System-Qt on Mac.
|
||||
#if defined(Q_OS_WIN) || defined(Q_OS_MAC)
|
||||
@@ -93,7 +90,7 @@ AbstractGdbAdapter::DumperHandling TermGdbAdapter::dumperHandling() const
|
||||
#endif
|
||||
}
|
||||
|
||||
void TermGdbAdapter::startAdapter()
|
||||
void GdbTermEngine::setupEngine()
|
||||
{
|
||||
QTC_ASSERT(state() == EngineSetupRequested, qDebug() << state());
|
||||
showMessage(_("TRYING TO START ADAPTER"));
|
||||
@@ -110,34 +107,32 @@ void TermGdbAdapter::startAdapter()
|
||||
m_stubProc.setWorkingDirectory(startParameters().workingDirectory);
|
||||
// Set environment + dumper preload.
|
||||
m_stubProc.setEnvironment(startParameters().environment);
|
||||
|
||||
connect(&m_stubProc, SIGNAL(processError(QString)), SLOT(stubError(QString)));
|
||||
connect(&m_stubProc, SIGNAL(processStarted()), SLOT(stubStarted()));
|
||||
connect(&m_stubProc, SIGNAL(wrapperStopped()), SLOT(stubExited()));
|
||||
// FIXME: Starting the stub implies starting the inferior. This is
|
||||
// fairly unclean as far as the state machine and error reporting go.
|
||||
|
||||
if (!m_stubProc.start(startParameters().executable,
|
||||
startParameters().processArgs)) {
|
||||
// Error message for user is delivered via a signal.
|
||||
m_engine->handleAdapterStartFailed(QString());
|
||||
handleAdapterStartFailed(QString());
|
||||
return;
|
||||
}
|
||||
|
||||
m_engine->startGdb();
|
||||
}
|
||||
|
||||
void TermGdbAdapter::handleGdbStartDone()
|
||||
void GdbTermEngine::stubStarted()
|
||||
{
|
||||
startGdb();
|
||||
}
|
||||
|
||||
void TermGdbAdapter::handleGdbStartFailed()
|
||||
void GdbTermEngine::handleGdbStartFailed()
|
||||
{
|
||||
m_stubProc.stop();
|
||||
}
|
||||
|
||||
void TermGdbAdapter::handleInferiorSetupOk()
|
||||
{
|
||||
QTC_ASSERT(state() == EngineSetupRequested, qDebug() << state());
|
||||
m_engine->handleAdapterStarted();
|
||||
}
|
||||
|
||||
void TermGdbAdapter::setupInferior()
|
||||
void GdbTermEngine::setupInferior()
|
||||
{
|
||||
QTC_ASSERT(state() == InferiorSetupRequested, qDebug() << state());
|
||||
const qint64 attachedPID = m_stubProc.applicationPID();
|
||||
@@ -147,12 +142,12 @@ void TermGdbAdapter::setupInferior()
|
||||
#else
|
||||
showMessage(QString::fromLatin1("Attaching to %1").arg(attachedPID), LogMisc);
|
||||
#endif
|
||||
m_engine->notifyInferiorPid(attachedPID);
|
||||
m_engine->postCommand("attach " + QByteArray::number(attachedPID),
|
||||
notifyInferiorPid(attachedPID);
|
||||
postCommand("attach " + QByteArray::number(attachedPID),
|
||||
CB(handleStubAttached));
|
||||
}
|
||||
|
||||
void TermGdbAdapter::handleStubAttached(const GdbResponse &response)
|
||||
void GdbTermEngine::handleStubAttached(const GdbResponse &response)
|
||||
{
|
||||
QTC_ASSERT(state() == InferiorSetupRequested, qDebug() << state());
|
||||
#ifdef Q_OS_WIN
|
||||
@@ -174,51 +169,51 @@ void TermGdbAdapter::handleStubAttached(const GdbResponse &response)
|
||||
#else
|
||||
showMessage(_("INFERIOR ATTACHED"));
|
||||
#endif // Q_OS_WIN
|
||||
m_engine->handleInferiorPrepared();
|
||||
handleInferiorPrepared();
|
||||
break;
|
||||
case GdbResultError:
|
||||
if (response.data.findChild("msg").data() == "ptrace: Operation not permitted.") {
|
||||
m_engine->notifyInferiorSetupFailed(DumperHelper::msgPtraceError(startParameters().startMode));
|
||||
notifyInferiorSetupFailed(DumperHelper::msgPtraceError(startParameters().startMode));
|
||||
break;
|
||||
}
|
||||
m_engine->notifyInferiorSetupFailed(QString::fromLocal8Bit(response.data.findChild("msg").data()));
|
||||
notifyInferiorSetupFailed(QString::fromLocal8Bit(response.data.findChild("msg").data()));
|
||||
break;
|
||||
default:
|
||||
m_engine->notifyInferiorSetupFailed(QString::fromLatin1("Invalid response %1").arg(response.resultClass));
|
||||
notifyInferiorSetupFailed(QString::fromLatin1("Invalid response %1").arg(response.resultClass));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void TermGdbAdapter::runEngine()
|
||||
void GdbTermEngine::runEngine()
|
||||
{
|
||||
QTC_ASSERT(state() == EngineRunRequested, qDebug() << state());
|
||||
m_engine->notifyEngineRunAndInferiorStopOk();
|
||||
m_engine->continueInferiorInternal();
|
||||
notifyEngineRunAndInferiorStopOk();
|
||||
continueInferiorInternal();
|
||||
}
|
||||
|
||||
void TermGdbAdapter::interruptInferior()
|
||||
void GdbTermEngine::interruptInferior2()
|
||||
{
|
||||
interruptLocalInferior(m_engine->inferiorPid());
|
||||
interruptLocalInferior(inferiorPid());
|
||||
}
|
||||
|
||||
void TermGdbAdapter::stubError(const QString &msg)
|
||||
void GdbTermEngine::stubError(const QString &msg)
|
||||
{
|
||||
showMessageBox(QMessageBox::Critical, tr("Debugger Error"), msg);
|
||||
}
|
||||
|
||||
void TermGdbAdapter::stubExited()
|
||||
void GdbTermEngine::stubExited()
|
||||
{
|
||||
if (state() == EngineShutdownRequested || state() == DebuggerFinished) {
|
||||
showMessage(_("STUB EXITED EXPECTEDLY"));
|
||||
return;
|
||||
}
|
||||
showMessage(_("STUB EXITED"));
|
||||
m_engine->notifyEngineIll();
|
||||
notifyEngineIll();
|
||||
}
|
||||
|
||||
void TermGdbAdapter::shutdownAdapter()
|
||||
void GdbTermEngine::shutdownEngine()
|
||||
{
|
||||
m_engine->notifyAdapterShutdownOk();
|
||||
notifyAdapterShutdownOk();
|
||||
}
|
||||
|
||||
} // namespace Internal
|
||||
|
||||
@@ -33,7 +33,7 @@
|
||||
#ifndef DEBUGGER_TERMGDBADAPTER_H
|
||||
#define DEBUGGER_TERMGDBADAPTER_H
|
||||
|
||||
#include "abstractgdbadapter.h"
|
||||
#include "gdbengine.h"
|
||||
#include "localgdbprocess.h"
|
||||
|
||||
#include <utils/consoleprocess.h>
|
||||
@@ -47,30 +47,31 @@ namespace Internal {
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
|
||||
class TermGdbAdapter : public AbstractGdbAdapter
|
||||
class GdbTermEngine : public GdbEngine
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit TermGdbAdapter(GdbEngine *engine);
|
||||
~TermGdbAdapter();
|
||||
GdbTermEngine(const DebuggerStartParameters &startParameters,
|
||||
DebuggerEngine *masterEngine);
|
||||
|
||||
~GdbTermEngine();
|
||||
|
||||
private:
|
||||
DumperHandling dumperHandling() const;
|
||||
|
||||
void startAdapter();
|
||||
void handleGdbStartDone();
|
||||
void setupEngine();
|
||||
void handleGdbStartFailed();
|
||||
void setupInferior();
|
||||
void runEngine();
|
||||
void interruptInferior();
|
||||
void shutdownAdapter();
|
||||
void interruptInferior2();
|
||||
void shutdownEngine();
|
||||
|
||||
AbstractGdbProcess *gdbProc() { return &m_gdbProc; }
|
||||
|
||||
void handleStubAttached(const GdbResponse &response);
|
||||
|
||||
Q_SLOT void handleInferiorSetupOk();
|
||||
Q_SLOT void stubStarted();
|
||||
Q_SLOT void stubExited();
|
||||
Q_SLOT void stubError(const QString &msg);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user