Commit 5d782df3 authored by hjk's avatar hjk Committed by hjk

debugger: Replace adapter classes by GdbEngine subclasses

Change-Id: Iee6195b1eed5251545b9d688221ac2edf19325c1
Reviewed-by: default avatarChristian Kandeler <christian.kandeler@nokia.com>
parent c68cf6dc
......@@ -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();
......
/**************************************************************************
**
** 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
/**************************************************************************
**
** 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")));
......
This diff is collapsed.
......@@ -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 {
//