forked from qt-creator/qt-creator
debugger: small refactoring of the access to the gdb process in the gdbengine
That's the first step to make the gdb/trk Adapter work with the otherwise unmodified gdb engine. GdbProcessBase is inherited by GdbProcess and the gdb/trk Adapter. In the GdbProcess case it's just a wrapper around a QProcess running gdb, in the Adapter case it's the interface to the gdb process in the whole rfomm/gdb/gdbserver combo.
This commit is contained in:
@@ -144,7 +144,7 @@ static QByteArray parsePlainConsoleStream(const GdbResultRecord &record)
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
|
||||
GdbEngine::GdbEngine(DebuggerManager *parent) :
|
||||
GdbEngine::GdbEngine(DebuggerManager *parent, GdbProcessBase *gdbProc) :
|
||||
#ifdef Q_OS_WIN // Do injection loading with MinGW (call loading does not work with 64bit)
|
||||
m_dumperInjectionLoad(true),
|
||||
#else
|
||||
@@ -153,6 +153,7 @@ GdbEngine::GdbEngine(DebuggerManager *parent) :
|
||||
q(parent),
|
||||
qq(parent->engineInterface())
|
||||
{
|
||||
m_gdbProc = gdbProc;
|
||||
m_stubProc.setMode(Core::Utils::ConsoleProcess::Debug);
|
||||
#ifdef Q_OS_UNIX
|
||||
m_stubProc.setSettings(Core::ICore::instance()->settings());
|
||||
@@ -164,19 +165,20 @@ GdbEngine::GdbEngine(DebuggerManager *parent) :
|
||||
GdbEngine::~GdbEngine()
|
||||
{
|
||||
// prevent sending error messages afterwards
|
||||
m_gdbProc.disconnect(this);
|
||||
m_gdbProc->disconnect(this);
|
||||
delete m_gdbProc;
|
||||
}
|
||||
|
||||
void GdbEngine::initializeConnections()
|
||||
{
|
||||
// Gdb Process interaction
|
||||
connect(&m_gdbProc, SIGNAL(error(QProcess::ProcessError)),
|
||||
connect(m_gdbProc, SIGNAL(error(QProcess::ProcessError)),
|
||||
this, SLOT(gdbProcError(QProcess::ProcessError)));
|
||||
connect(&m_gdbProc, SIGNAL(readyReadStandardOutput()),
|
||||
connect(m_gdbProc, SIGNAL(readyReadStandardOutput()),
|
||||
this, SLOT(readGdbStandardOutput()));
|
||||
connect(&m_gdbProc, SIGNAL(readyReadStandardError()),
|
||||
connect(m_gdbProc, SIGNAL(readyReadStandardError()),
|
||||
this, SLOT(readGdbStandardError()));
|
||||
connect(&m_gdbProc, SIGNAL(finished(int, QProcess::ExitStatus)),
|
||||
connect(m_gdbProc, SIGNAL(finished(int, QProcess::ExitStatus)),
|
||||
q, SLOT(exitDebugger()));
|
||||
|
||||
connect(&m_stubProc, SIGNAL(processError(QString)),
|
||||
@@ -614,7 +616,7 @@ void GdbEngine::stubError(const QString &msg)
|
||||
|
||||
void GdbEngine::readGdbStandardError()
|
||||
{
|
||||
qWarning() << "Unexpected gdb stderr:" << m_gdbProc.readAllStandardError();
|
||||
qWarning() << "Unexpected gdb stderr:" << m_gdbProc->readAllStandardError();
|
||||
}
|
||||
|
||||
void GdbEngine::readGdbStandardOutput()
|
||||
@@ -622,7 +624,7 @@ void GdbEngine::readGdbStandardOutput()
|
||||
int newstart = 0;
|
||||
int scan = m_inbuffer.size();
|
||||
|
||||
m_inbuffer.append(m_gdbProc.readAllStandardOutput());
|
||||
m_inbuffer.append(m_gdbProc->readAllStandardOutput());
|
||||
|
||||
while (newstart < m_inbuffer.size()) {
|
||||
int start = newstart;
|
||||
@@ -651,7 +653,7 @@ void GdbEngine::interruptInferior()
|
||||
{
|
||||
qq->notifyInferiorStopRequested();
|
||||
|
||||
if (m_gdbProc.state() == QProcess::NotRunning) {
|
||||
if (m_gdbProc->state() == QProcess::NotRunning) {
|
||||
debugMessage(_("TRYING TO INTERRUPT INFERIOR WITHOUT RUNNING GDB"));
|
||||
qq->notifyInferiorExited();
|
||||
return;
|
||||
@@ -698,7 +700,7 @@ void GdbEngine::postCommand(const QString &command, GdbCommandFlags flags,
|
||||
GdbCommandCallback callback, const char *callbackName,
|
||||
const QVariant &cookie)
|
||||
{
|
||||
if (m_gdbProc.state() == QProcess::NotRunning) {
|
||||
if (m_gdbProc->state() == QProcess::NotRunning) {
|
||||
debugMessage(_("NO GDB PROCESS RUNNING, CMD IGNORED: ") + command);
|
||||
return;
|
||||
}
|
||||
@@ -742,7 +744,7 @@ void GdbEngine::flushCommand(GdbCommand &cmd)
|
||||
if (cmd.flags & EmbedToken)
|
||||
cmd.command = cmd.command.arg(currentToken());
|
||||
|
||||
m_gdbProc.write(cmd.command.toLatin1() + "\r\n");
|
||||
m_gdbProc->write(cmd.command.toLatin1() + "\r\n");
|
||||
//emit gdbInputAvailable(QString(), " " + currentTime());
|
||||
//emit gdbInputAvailable(QString(), "[" + currentTime() + "] " + cmd.command);
|
||||
emit gdbInputAvailable(LogInput, cmd.command);
|
||||
@@ -829,12 +831,12 @@ void GdbEngine::handleResultRecord(const GdbResultRecord &record)
|
||||
|
||||
void GdbEngine::executeDebuggerCommand(const QString &command)
|
||||
{
|
||||
if (m_gdbProc.state() == QProcess::NotRunning) {
|
||||
if (m_gdbProc->state() == QProcess::NotRunning) {
|
||||
debugMessage(_("NO GDB PROCESS RUNNING, PLAIN CMD IGNORED: ") + command);
|
||||
return;
|
||||
}
|
||||
|
||||
m_gdbProc.write(command.toLocal8Bit() + "\r\n");
|
||||
m_gdbProc->write(command.toLocal8Bit() + "\r\n");
|
||||
}
|
||||
|
||||
void GdbEngine::handleTargetCore(const GdbResultRecord &, const QVariant &)
|
||||
@@ -1434,15 +1436,15 @@ void GdbEngine::detachDebugger()
|
||||
|
||||
void GdbEngine::exitDebugger()
|
||||
{
|
||||
debugMessage(_("GDBENGINE EXITDEBUGGER: %1").arg(m_gdbProc.state()));
|
||||
if (m_gdbProc.state() == QProcess::Starting) {
|
||||
debugMessage(_("GDBENGINE EXITDEBUGGER: %1").arg(m_gdbProc->state()));
|
||||
if (m_gdbProc->state() == QProcess::Starting) {
|
||||
debugMessage(_("WAITING FOR GDB STARTUP TO SHUTDOWN: %1")
|
||||
.arg(m_gdbProc.state()));
|
||||
m_gdbProc.waitForStarted();
|
||||
.arg(m_gdbProc->state()));
|
||||
m_gdbProc->waitForStarted();
|
||||
}
|
||||
if (m_gdbProc.state() == QProcess::Running) {
|
||||
if (m_gdbProc->state() == QProcess::Running) {
|
||||
debugMessage(_("WAITING FOR RUNNING GDB TO SHUTDOWN: %1")
|
||||
.arg(m_gdbProc.state()));
|
||||
.arg(m_gdbProc->state()));
|
||||
if (q->status() != DebuggerInferiorStopped
|
||||
&& q->status() != DebuggerProcessStartingUp) {
|
||||
QTC_ASSERT(q->status() == DebuggerInferiorRunning,
|
||||
@@ -1455,17 +1457,17 @@ void GdbEngine::exitDebugger()
|
||||
postCommand(_("kill"));
|
||||
postCommand(_("-gdb-exit"), CB(handleExit));
|
||||
// 20s can easily happen when loading webkit debug information
|
||||
if (!m_gdbProc.waitForFinished(20000)) {
|
||||
if (!m_gdbProc->waitForFinished(20000)) {
|
||||
debugMessage(_("FORCING TERMINATION: %1")
|
||||
.arg(m_gdbProc.state()));
|
||||
m_gdbProc.terminate();
|
||||
m_gdbProc.waitForFinished(20000);
|
||||
.arg(m_gdbProc->state()));
|
||||
m_gdbProc->terminate();
|
||||
m_gdbProc->waitForFinished(20000);
|
||||
}
|
||||
}
|
||||
if (m_gdbProc.state() != QProcess::NotRunning) {
|
||||
if (m_gdbProc->state() != QProcess::NotRunning) {
|
||||
debugMessage(_("PROBLEM STOPPING DEBUGGER: STATE %1")
|
||||
.arg(m_gdbProc.state()));
|
||||
m_gdbProc.kill();
|
||||
.arg(m_gdbProc->state()));
|
||||
m_gdbProc->kill();
|
||||
}
|
||||
|
||||
m_outputCollector.shutdown();
|
||||
@@ -1487,9 +1489,9 @@ bool GdbEngine::startDebugger(const QSharedPointer<DebuggerStartParameters> &sp)
|
||||
|
||||
QStringList gdbArgs;
|
||||
|
||||
if (m_gdbProc.state() != QProcess::NotRunning) {
|
||||
debugMessage(_("GDB IS ALREADY RUNNING, STATE: %1").arg(m_gdbProc.state()));
|
||||
m_gdbProc.kill();
|
||||
if (m_gdbProc->state() != QProcess::NotRunning) {
|
||||
debugMessage(_("GDB IS ALREADY RUNNING, STATE: %1").arg(m_gdbProc->state()));
|
||||
m_gdbProc->kill();
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -1529,16 +1531,16 @@ bool GdbEngine::startDebugger(const QSharedPointer<DebuggerStartParameters> &sp)
|
||||
gdbArgs.prepend(_("--tty=") + m_outputCollector.serverName());
|
||||
|
||||
if (!sp->workingDir.isEmpty())
|
||||
m_gdbProc.setWorkingDirectory(sp->workingDir);
|
||||
m_gdbProc->setWorkingDirectory(sp->workingDir);
|
||||
if (!sp->environment.isEmpty())
|
||||
m_gdbProc.setEnvironment(sp->environment);
|
||||
m_gdbProc->setEnvironment(sp->environment);
|
||||
}
|
||||
|
||||
#if 0
|
||||
qDebug() << "Command:" << q->settings()->m_gdbCmd;
|
||||
qDebug() << "WorkingDirectory:" << m_gdbProc.workingDirectory();
|
||||
qDebug() << "WorkingDirectory:" << m_gdbProc->workingDirectory();
|
||||
qDebug() << "ScriptFile:" << q->settings()->m_scriptFile;
|
||||
qDebug() << "Environment:" << m_gdbProc.environment();
|
||||
qDebug() << "Environment:" << m_gdbProc->environment();
|
||||
qDebug() << "Arguments:" << gdbArgs;
|
||||
qDebug() << "BuildDir:" << sp->buildDir;
|
||||
qDebug() << "ExeFile:" << sp->executable;
|
||||
@@ -1546,10 +1548,10 @@ bool GdbEngine::startDebugger(const QSharedPointer<DebuggerStartParameters> &sp)
|
||||
|
||||
QString loc = theDebuggerStringSetting(GdbLocation);
|
||||
q->showStatusMessage(tr("Starting Debugger: ") + loc + _c(' ') + gdbArgs.join(_(" ")));
|
||||
m_gdbProc.start(loc, gdbArgs);
|
||||
if (!m_gdbProc.waitForStarted()) {
|
||||
m_gdbProc->start(loc, gdbArgs);
|
||||
if (!m_gdbProc->waitForStarted()) {
|
||||
QMessageBox::critical(q->mainWindow(), tr("Debugger Startup Failure"),
|
||||
tr("Cannot start debugger: %1").arg(m_gdbProc.errorString()));
|
||||
tr("Cannot start debugger: %1").arg(m_gdbProc->errorString()));
|
||||
m_outputCollector.shutdown();
|
||||
m_stubProc.blockSignals(true);
|
||||
m_stubProc.stop();
|
||||
@@ -4198,7 +4200,7 @@ void GdbEngine::handleFetchDisassemblerByAddress0(const GdbResultRecord &record,
|
||||
IDebuggerEngine *createGdbEngine(DebuggerManager *parent, QList<Core::IOptionsPage*> *opts)
|
||||
{
|
||||
opts->push_back(new GdbOptionsPage);
|
||||
return new GdbEngine(parent);
|
||||
return new GdbEngine(parent, new GdbProcess);
|
||||
}
|
||||
|
||||
} // namespace Internal
|
||||
|
||||
@@ -56,6 +56,7 @@ QT_END_NAMESPACE
|
||||
namespace Debugger {
|
||||
namespace Internal {
|
||||
|
||||
|
||||
class DebuggerManager;
|
||||
class IDebuggerManagerAccessForEngines;
|
||||
class GdbResultRecord;
|
||||
@@ -72,13 +73,78 @@ enum DebuggingHelperState
|
||||
DebuggingHelperUnavailable,
|
||||
};
|
||||
|
||||
// GdbProcessBase is inherited by GdbProcess and the gdb/trk Adapter.
|
||||
// In the GdbProcess case it's just a wrapper around a QProcess running
|
||||
// gdb, in the Adapter case it's the interface to the gdb process in
|
||||
// the whole rfomm/gdb/gdbserver combo.
|
||||
class GdbProcessBase : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
GdbProcessBase(QObject *parent) : QObject(parent) {}
|
||||
|
||||
virtual void start(const QString &program, const QStringList &args,
|
||||
QIODevice::OpenMode mode = QIODevice::ReadWrite) = 0;
|
||||
virtual void kill() = 0;
|
||||
virtual void terminate() = 0;
|
||||
virtual bool waitForStarted(int msecs = 30000) = 0;
|
||||
virtual bool waitForFinished(int msecs = 30000) = 0;
|
||||
virtual QProcess::ProcessState state() const = 0;
|
||||
virtual QString errorString() const = 0;
|
||||
virtual QByteArray readAllStandardError() = 0;
|
||||
virtual QByteArray readAllStandardOutput() = 0;
|
||||
virtual qint64 write(const char *data) = 0;
|
||||
virtual void setWorkingDirectory(const QString &dir) = 0;
|
||||
virtual void setEnvironment(const QStringList &env) = 0;
|
||||
|
||||
signals:
|
||||
void error(QProcess::ProcessError);
|
||||
void readyReadStandardOutput();
|
||||
void readyReadStandardError();
|
||||
void finished(int, QProcess::ExitStatus);
|
||||
};
|
||||
|
||||
class GdbProcess : public GdbProcessBase
|
||||
{
|
||||
public:
|
||||
GdbProcess(QObject *parent = 0)
|
||||
: GdbProcessBase(parent)
|
||||
{
|
||||
connect(&m_proc, SIGNAL(error(QProcess::ProcessError)),
|
||||
this, SIGNAL(error(QProcess::ProcessError)));
|
||||
connect(&m_proc, SIGNAL(readyReadStandardOutput()),
|
||||
this, SIGNAL(readyReadStandardOutput()));
|
||||
connect(&m_proc, SIGNAL(readyReadStandardError()),
|
||||
this, SIGNAL(readyReadStandardError()));
|
||||
connect(&m_proc, SIGNAL(finished(int, QProcess::ExitStatus)),
|
||||
this, SIGNAL(finished(int, QProcess::ExitStatus)));
|
||||
}
|
||||
|
||||
void start(const QString &program, const QStringList &args,
|
||||
QIODevice::OpenMode mode) { m_proc.start(program, args, mode); }
|
||||
void kill() { m_proc.kill(); }
|
||||
void terminate() { m_proc.terminate(); }
|
||||
bool waitForStarted(int msecs) { return m_proc.waitForStarted(msecs); }
|
||||
bool waitForFinished(int msecs) { return m_proc.waitForFinished(msecs); }
|
||||
QProcess::ProcessState state() const { return m_proc.state(); }
|
||||
QString errorString() const { return m_proc.errorString(); }
|
||||
QByteArray readAllStandardError() { return m_proc.readAllStandardError(); }
|
||||
QByteArray readAllStandardOutput() { return m_proc.readAllStandardOutput(); }
|
||||
qint64 write(const char *data) { return m_proc.write(data); }
|
||||
void setWorkingDirectory(const QString &dir) { m_proc.setWorkingDirectory(dir); }
|
||||
void setEnvironment(const QStringList &env) { m_proc.setEnvironment(env); }
|
||||
|
||||
private:
|
||||
QProcess m_proc;
|
||||
};
|
||||
|
||||
class GdbEngine : public IDebuggerEngine
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
GdbEngine(DebuggerManager *parent);
|
||||
GdbEngine(DebuggerManager *parent, GdbProcessBase *gdbProc);
|
||||
~GdbEngine();
|
||||
|
||||
signals:
|
||||
@@ -251,7 +317,7 @@ private:
|
||||
|
||||
QByteArray m_inbuffer;
|
||||
|
||||
QProcess m_gdbProc;
|
||||
GdbProcessBase *m_gdbProc;
|
||||
QProcess m_uploadProc;
|
||||
|
||||
Core::Utils::ConsoleProcess m_stubProc;
|
||||
|
||||
Reference in New Issue
Block a user