forked from qt-creator/qt-creator
debugger: rework startup logic
This commit is contained in:
@@ -33,6 +33,8 @@
|
|||||||
#include <QtCore/QObject>
|
#include <QtCore/QObject>
|
||||||
#include <QtCore/QProcess>
|
#include <QtCore/QProcess>
|
||||||
|
|
||||||
|
#include "gdbengine.h"
|
||||||
|
|
||||||
namespace Debugger {
|
namespace Debugger {
|
||||||
namespace Internal {
|
namespace Internal {
|
||||||
|
|
||||||
@@ -48,15 +50,10 @@ class AbstractGdbAdapter : public QObject
|
|||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
public:
|
public:
|
||||||
AbstractGdbAdapter(QObject *parent = 0) : QObject(parent) {}
|
AbstractGdbAdapter(GdbEngine *engine, QObject *parent = 0)
|
||||||
|
: QObject(parent), m_engine(engine)
|
||||||
|
{}
|
||||||
|
|
||||||
virtual void setEngine(GdbEngine *engine) { m_engine = engine; }
|
|
||||||
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 QProcess::ProcessState state() const = 0;
|
||||||
virtual QString errorString() const = 0;
|
virtual QString errorString() const = 0;
|
||||||
virtual QByteArray readAllStandardError() = 0;
|
virtual QByteArray readAllStandardError() = 0;
|
||||||
@@ -66,18 +63,35 @@ public:
|
|||||||
virtual void setEnvironment(const QStringList &env) = 0;
|
virtual void setEnvironment(const QStringList &env) = 0;
|
||||||
virtual bool isAdapter() const = 0;
|
virtual bool isAdapter() const = 0;
|
||||||
|
|
||||||
virtual void attach() = 0;
|
virtual void startAdapter(const DebuggerStartParametersPtr &sp) = 0;
|
||||||
|
virtual void prepareInferior() = 0;
|
||||||
|
virtual void startInferior() = 0;
|
||||||
|
virtual void shutdownInferior() = 0;
|
||||||
|
virtual void shutdownAdapter() = 0;
|
||||||
virtual void interruptInferior() = 0;
|
virtual void interruptInferior() = 0;
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
|
void adapterStarted();
|
||||||
|
void adapterStartFailed(const QString &msg);
|
||||||
|
void adapterShutDown();
|
||||||
|
void adapterShutdownFailed(const QString &msg);
|
||||||
|
void adapterCrashed();
|
||||||
|
|
||||||
|
void inferiorPrepared();
|
||||||
|
void inferiorPreparationFailed(const QString &msg);
|
||||||
|
void inferiorStarted();
|
||||||
|
void inferiorStartFailed(const QString &msg);
|
||||||
|
void inferiorShutDown();
|
||||||
|
void inferiorShutdownFailed(const QString &msg);
|
||||||
|
|
||||||
|
void inferiorPidChanged(qint64 pid);
|
||||||
|
|
||||||
void error(QProcess::ProcessError);
|
void error(QProcess::ProcessError);
|
||||||
void started();
|
|
||||||
void readyReadStandardOutput();
|
void readyReadStandardOutput();
|
||||||
void readyReadStandardError();
|
void readyReadStandardError();
|
||||||
void finished(int, QProcess::ExitStatus);
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
GdbEngine *m_engine;
|
GdbEngine * const m_engine;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace Internal
|
} // namespace Internal
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ include(../../../shared/trk/trk.pri)
|
|||||||
|
|
||||||
HEADERS += \
|
HEADERS += \
|
||||||
$$PWD/abstractgdbadapter.h \
|
$$PWD/abstractgdbadapter.h \
|
||||||
|
$$PWD/plaingdbadapter.h \
|
||||||
$$PWD/gdbmi.h \
|
$$PWD/gdbmi.h \
|
||||||
$$PWD/gdbengine.h \
|
$$PWD/gdbengine.h \
|
||||||
$$PWD/gdboptionspage.h \
|
$$PWD/gdboptionspage.h \
|
||||||
@@ -14,10 +15,11 @@ SOURCES += \
|
|||||||
$$PWD/gdbmi.cpp \
|
$$PWD/gdbmi.cpp \
|
||||||
$$PWD/gdbengine.cpp \
|
$$PWD/gdbengine.cpp \
|
||||||
$$PWD/gdboptionspage.cpp \
|
$$PWD/gdboptionspage.cpp \
|
||||||
$$PWD/trkgdbadapter.cpp \
|
$$PWD/plaingdbadapter.cpp \
|
||||||
$$PWD/trkoptions.cpp \
|
$$PWD/trkoptions.cpp \
|
||||||
$$PWD/trkoptionswidget.cpp \
|
$$PWD/trkoptionswidget.cpp \
|
||||||
$$PWD/trkoptionspage.cpp
|
$$PWD/trkoptionspage.cpp \
|
||||||
|
$$PWD/trkgdbadapter.cpp
|
||||||
|
|
||||||
FORMS += $$PWD/gdboptionspage.ui \
|
FORMS += $$PWD/gdboptionspage.ui \
|
||||||
$$PWD/trkoptionswidget.ui
|
$$PWD/trkoptionswidget.ui
|
||||||
|
|||||||
@@ -33,6 +33,7 @@
|
|||||||
#include "gdboptionspage.h"
|
#include "gdboptionspage.h"
|
||||||
#include "trkoptions.h"
|
#include "trkoptions.h"
|
||||||
#include "trkoptionspage.h"
|
#include "trkoptionspage.h"
|
||||||
|
#include "plaingdbadapter.h"
|
||||||
#include "trkgdbadapter.h"
|
#include "trkgdbadapter.h"
|
||||||
|
|
||||||
#include "watchutils.h"
|
#include "watchutils.h"
|
||||||
@@ -82,6 +83,9 @@
|
|||||||
#endif
|
#endif
|
||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
|
|
||||||
|
static QString lastFile;
|
||||||
|
static int lastLine;
|
||||||
|
|
||||||
namespace Debugger {
|
namespace Debugger {
|
||||||
namespace Internal {
|
namespace Internal {
|
||||||
using namespace Debugger::Constants;
|
using namespace Debugger::Constants;
|
||||||
@@ -141,44 +145,13 @@ static QByteArray parsePlainConsoleStream(const GdbResultRecord &record)
|
|||||||
return out.mid(pos + 3);
|
return out.mid(pos + 3);
|
||||||
}
|
}
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////
|
|
||||||
//
|
|
||||||
// PlainGdbAdapter
|
|
||||||
//
|
|
||||||
///////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
void PlainGdbAdapter::attach()
|
|
||||||
{
|
|
||||||
QFileInfo fi(m_engine->startParameters().executable);
|
|
||||||
m_engine->postCommand(_("-file-exec-and-symbols \"%1\"").arg(fi.absoluteFilePath()),
|
|
||||||
&GdbEngine::handleFileExecAndSymbols, "handleFileExecAndSymbols");
|
|
||||||
}
|
|
||||||
|
|
||||||
void PlainGdbAdapter::interruptInferior()
|
|
||||||
{
|
|
||||||
if (m_engine->startMode() == StartRemote) {
|
|
||||||
m_engine->postCommand(_("-exec-interrupt"));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const qint64 attachedPID = m_engine->inferiorPid();
|
|
||||||
if (attachedPID <= 0) {
|
|
||||||
m_engine->debugMessage(
|
|
||||||
_("TRYING TO INTERRUPT INFERIOR BEFORE PID WAS OBTAINED"));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!interruptProcess(attachedPID))
|
|
||||||
m_engine->debugMessage(_("CANNOT INTERRUPT %1").arg(attachedPID));
|
|
||||||
}
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////
|
||||||
//
|
//
|
||||||
// GdbEngine
|
// GdbEngine
|
||||||
//
|
//
|
||||||
///////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
GdbEngine::GdbEngine(DebuggerManager *parent, AbstractGdbAdapter *gdbAdapter) :
|
GdbEngine::GdbEngine(DebuggerManager *parent) :
|
||||||
#ifdef Q_OS_WIN // Do injection loading with MinGW (call loading does not work with 64bit)
|
#ifdef Q_OS_WIN // Do injection loading with MinGW (call loading does not work with 64bit)
|
||||||
m_dumperInjectionLoad(true),
|
m_dumperInjectionLoad(true),
|
||||||
#else
|
#else
|
||||||
@@ -187,21 +160,24 @@ GdbEngine::GdbEngine(DebuggerManager *parent, AbstractGdbAdapter *gdbAdapter) :
|
|||||||
m_manager(parent),
|
m_manager(parent),
|
||||||
qq(parent->engineInterface())
|
qq(parent->engineInterface())
|
||||||
{
|
{
|
||||||
m_gdbAdapter = gdbAdapter;
|
m_gdbAdapter = 0;
|
||||||
m_gdbAdapter->setEngine(this);
|
|
||||||
m_stubProc.setMode(Core::Utils::ConsoleProcess::Debug);
|
|
||||||
#ifdef Q_OS_UNIX
|
|
||||||
m_stubProc.setSettings(Core::ICore::instance()->settings());
|
|
||||||
#endif
|
|
||||||
initializeVariables();
|
|
||||||
initializeConnections();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
GdbEngine::~GdbEngine()
|
GdbEngine::~GdbEngine()
|
||||||
{
|
{
|
||||||
// prevent sending error messages afterwards
|
// prevent sending error messages afterwards
|
||||||
|
if (m_gdbAdapter) {
|
||||||
m_gdbAdapter->disconnect(this);
|
m_gdbAdapter->disconnect(this);
|
||||||
delete m_gdbAdapter;
|
delete m_gdbAdapter;
|
||||||
|
m_gdbAdapter = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void GdbEngine::setGdbAdapter(AbstractGdbAdapter *gdbAdapter)
|
||||||
|
{
|
||||||
|
m_gdbAdapter = gdbAdapter;
|
||||||
|
initializeVariables();
|
||||||
|
initializeConnections();
|
||||||
}
|
}
|
||||||
|
|
||||||
void GdbEngine::initializeConnections()
|
void GdbEngine::initializeConnections()
|
||||||
@@ -213,16 +189,31 @@ void GdbEngine::initializeConnections()
|
|||||||
this, SLOT(readGdbStandardOutput()));
|
this, SLOT(readGdbStandardOutput()));
|
||||||
connect(m_gdbAdapter, SIGNAL(readyReadStandardError()),
|
connect(m_gdbAdapter, SIGNAL(readyReadStandardError()),
|
||||||
this, SLOT(readGdbStandardError()));
|
this, SLOT(readGdbStandardError()));
|
||||||
connect(m_gdbAdapter, SIGNAL(finished(int, QProcess::ExitStatus)),
|
|
||||||
m_manager, SLOT(exitDebugger()));
|
|
||||||
connect(m_gdbAdapter, SIGNAL(started()),
|
|
||||||
this, SLOT(startDebugger2()));
|
|
||||||
|
|
||||||
connect(&m_stubProc, SIGNAL(processError(QString)),
|
connect(m_gdbAdapter, SIGNAL(adapterStarted()),
|
||||||
this, SLOT(stubError(QString)));
|
this, SLOT(handleAdapterStarted()));
|
||||||
connect(&m_stubProc, SIGNAL(processStarted()),
|
connect(m_gdbAdapter, SIGNAL(adapterStartFailed(QString)),
|
||||||
this, SLOT(stubStarted()));
|
this, SLOT(handleAdapterStartFailed(QString)));
|
||||||
connect(&m_stubProc, SIGNAL(wrapperStopped()),
|
connect(m_gdbAdapter, SIGNAL(adapterShutDown()),
|
||||||
|
this, SLOT(handleAdapterShutDown()));
|
||||||
|
connect(m_gdbAdapter, SIGNAL(adapterShutdownFailed(QString)),
|
||||||
|
this, SLOT(handleAdapterShutdownFailed(QString)));
|
||||||
|
|
||||||
|
connect(m_gdbAdapter, SIGNAL(inferiorPrepared()),
|
||||||
|
this, SLOT(handleInferiorPrepared()));
|
||||||
|
connect(m_gdbAdapter, SIGNAL(inferiorPreparationFailed(QString)),
|
||||||
|
this, SLOT(handleInferiorPreparationFailed(QString)));
|
||||||
|
|
||||||
|
connect(m_gdbAdapter, SIGNAL(inferiorStarted()),
|
||||||
|
this, SLOT(handleInferiorStarted()));
|
||||||
|
connect(m_gdbAdapter, SIGNAL(inferiorStartFailed(QString)),
|
||||||
|
this, SLOT(handleInferiorStartFailed(QString)));
|
||||||
|
connect(m_gdbAdapter, SIGNAL(inferiorShutDown()),
|
||||||
|
this, SLOT(handleInferiorShutDown()));
|
||||||
|
connect(m_gdbAdapter, SIGNAL(inferiorShutdownFailed(QString)),
|
||||||
|
this, SLOT(handleInferiorShutdownFailed(QString)));
|
||||||
|
|
||||||
|
connect(m_gdbAdapter, SIGNAL(adapterCrashed()),
|
||||||
m_manager, SLOT(exitDebugger()));
|
m_manager, SLOT(exitDebugger()));
|
||||||
|
|
||||||
connect(&m_uploadProc, SIGNAL(error(QProcess::ProcessError)),
|
connect(&m_uploadProc, SIGNAL(error(QProcess::ProcessError)),
|
||||||
@@ -269,7 +260,7 @@ void GdbEngine::initializeVariables()
|
|||||||
m_oldestAcceptableToken = -1;
|
m_oldestAcceptableToken = -1;
|
||||||
m_outputCodec = QTextCodec::codecForLocale();
|
m_outputCodec = QTextCodec::codecForLocale();
|
||||||
m_pendingRequests = 0;
|
m_pendingRequests = 0;
|
||||||
m_autoContinue = false;
|
m_continuationAfterDone = 0;
|
||||||
m_waitingForFirstBreakpointToBeHit = false;
|
m_waitingForFirstBreakpointToBeHit = false;
|
||||||
m_commandsToRunOnTemporaryBreak.clear();
|
m_commandsToRunOnTemporaryBreak.clear();
|
||||||
m_cookieForToken.clear();
|
m_cookieForToken.clear();
|
||||||
@@ -287,10 +278,8 @@ void GdbEngine::initializeVariables()
|
|||||||
|
|
||||||
// FIXME: unhandled:
|
// FIXME: unhandled:
|
||||||
//m_outputCodecState = QTextCodec::ConverterState();
|
//m_outputCodecState = QTextCodec::ConverterState();
|
||||||
//OutputCollector m_outputCollector;
|
|
||||||
//QProcess m_gdbAdapter;
|
//QProcess m_gdbAdapter;
|
||||||
//QProcess m_uploadProc;
|
//QProcess m_uploadProc;
|
||||||
//Core::Utils::ConsoleProcess m_stubProc;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void GdbEngine::gdbProcError(QProcess::ProcessError error)
|
void GdbEngine::gdbProcError(QProcess::ProcessError error)
|
||||||
@@ -544,11 +533,13 @@ void GdbEngine::handleResponse(const QByteArray &buff)
|
|||||||
}
|
}
|
||||||
|
|
||||||
case '~': {
|
case '~': {
|
||||||
|
static QRegExp re(_("New .hread 0x[0-9a-f]* \\(LWP ([0-9]*)\\)"));
|
||||||
QByteArray data = GdbMi::parseCString(from, to);
|
QByteArray data = GdbMi::parseCString(from, to);
|
||||||
m_pendingConsoleStreamOutput += data;
|
m_pendingConsoleStreamOutput += data;
|
||||||
if (data.startsWith("Reading symbols from ")) {
|
if (re.indexIn(_(data)) != -1)
|
||||||
|
maybeHandleInferiorPidChanged(re.cap(1));
|
||||||
|
if (data.startsWith("Reading symbols from "))
|
||||||
showStatusMessage(tr("Reading %1...").arg(_(data.mid(21))));
|
showStatusMessage(tr("Reading %1...").arg(_(data.mid(21))));
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -633,25 +624,6 @@ void GdbEngine::handleResponse(const QByteArray &buff)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void GdbEngine::handleStubAttached(const GdbResultRecord &, const QVariant &)
|
|
||||||
{
|
|
||||||
qq->notifyInferiorStopped();
|
|
||||||
handleAqcuiredInferior();
|
|
||||||
m_autoContinue = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void GdbEngine::stubStarted()
|
|
||||||
{
|
|
||||||
const qint64 attachedPID = m_stubProc.applicationPID();
|
|
||||||
qq->notifyInferiorPidChanged(attachedPID);
|
|
||||||
postCommand(_("attach %1").arg(attachedPID), CB(handleStubAttached));
|
|
||||||
}
|
|
||||||
|
|
||||||
void GdbEngine::stubError(const QString &msg)
|
|
||||||
{
|
|
||||||
QMessageBox::critical(mainWindow(), tr("Debugger Error"), msg);
|
|
||||||
}
|
|
||||||
|
|
||||||
void GdbEngine::readGdbStandardError()
|
void GdbEngine::readGdbStandardError()
|
||||||
{
|
{
|
||||||
qWarning() << "Unexpected gdb stderr:" << m_gdbAdapter->readAllStandardError();
|
qWarning() << "Unexpected gdb stderr:" << m_gdbAdapter->readAllStandardError();
|
||||||
@@ -717,6 +689,18 @@ void GdbEngine::maybeHandleInferiorPidChanged(const QString &pid0)
|
|||||||
tryLoadDebuggingHelpers();
|
tryLoadDebuggingHelpers();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void GdbEngine::postCommand(const QString &command, 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 QString &command, GdbCommandCallback callback,
|
void GdbEngine::postCommand(const QString &command, GdbCommandCallback callback,
|
||||||
const char *callbackName, const QVariant &cookie)
|
const char *callbackName, const QVariant &cookie)
|
||||||
{
|
{
|
||||||
@@ -727,28 +711,32 @@ void GdbEngine::postCommand(const QString &command, GdbCommandFlags flags,
|
|||||||
GdbCommandCallback callback, const char *callbackName,
|
GdbCommandCallback callback, const char *callbackName,
|
||||||
const QVariant &cookie)
|
const QVariant &cookie)
|
||||||
{
|
{
|
||||||
if (m_gdbAdapter->state() == QProcess::NotRunning) {
|
|
||||||
debugMessage(_("NO GDB PROCESS RUNNING, CMD IGNORED: ") + command);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (flags & RebuildModel) {
|
|
||||||
++m_pendingRequests;
|
|
||||||
PENDING_DEBUG(" CALLBACK" << callbackName << "INCREMENTS PENDING TO:"
|
|
||||||
<< m_pendingRequests << command);
|
|
||||||
} else {
|
|
||||||
PENDING_DEBUG(" UNKNOWN CALLBACK" << callbackName << "LEAVES PENDING AT:"
|
|
||||||
<< m_pendingRequests << command);
|
|
||||||
}
|
|
||||||
|
|
||||||
GdbCommand cmd;
|
GdbCommand cmd;
|
||||||
cmd.command = command;
|
cmd.command = command;
|
||||||
cmd.flags = flags;
|
cmd.flags = flags;
|
||||||
cmd.callback = callback;
|
cmd.callback = callback;
|
||||||
cmd.callbackName = callbackName;
|
cmd.callbackName = callbackName;
|
||||||
cmd.cookie = cookie;
|
cmd.cookie = cookie;
|
||||||
|
postCommandHelper(cmd);
|
||||||
|
}
|
||||||
|
|
||||||
if ((flags & NeedsStop) && status() != DebuggerInferiorStopped
|
void GdbEngine::postCommandHelper(const GdbCommand &cmd)
|
||||||
|
{
|
||||||
|
if (m_gdbAdapter->state() == QProcess::NotRunning) {
|
||||||
|
debugMessage(_("NO GDB PROCESS RUNNING, CMD IGNORED: ") + cmd.command);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cmd.flags & RebuildModel) {
|
||||||
|
++m_pendingRequests;
|
||||||
|
PENDING_DEBUG(" CALLBACK" << cmd.callbackName
|
||||||
|
<< "INCREMENTS PENDING TO:" << m_pendingRequests << cmd.command);
|
||||||
|
} else {
|
||||||
|
PENDING_DEBUG(" UNKNOWN CALLBACK" << cmd.callbackName
|
||||||
|
<< "LEAVES PENDING AT:" << m_pendingRequests << cmd.command);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((cmd.flags & NeedsStop) && status() != DebuggerInferiorStopped
|
||||||
&& status() != DebuggerProcessStartingUp) {
|
&& status() != DebuggerProcessStartingUp) {
|
||||||
// queue the commands that we cannot send at once
|
// queue the commands that we cannot send at once
|
||||||
QTC_ASSERT(status() == DebuggerInferiorRunning,
|
QTC_ASSERT(status() == DebuggerInferiorRunning,
|
||||||
@@ -757,13 +745,14 @@ void GdbEngine::postCommand(const QString &command, GdbCommandFlags flags,
|
|||||||
debugMessage(_("QUEUING COMMAND ") + cmd.command);
|
debugMessage(_("QUEUING COMMAND ") + cmd.command);
|
||||||
m_commandsToRunOnTemporaryBreak.append(cmd);
|
m_commandsToRunOnTemporaryBreak.append(cmd);
|
||||||
interruptInferior();
|
interruptInferior();
|
||||||
} else if (!command.isEmpty()) {
|
} else if (!cmd.command.isEmpty()) {
|
||||||
flushCommand(cmd);
|
flushCommand(cmd);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void GdbEngine::flushCommand(GdbCommand &cmd)
|
void GdbEngine::flushCommand(const GdbCommand &cmd0)
|
||||||
{
|
{
|
||||||
|
GdbCommand cmd = cmd0;
|
||||||
if (m_gdbAdapter->state() != QProcess::Running) {
|
if (m_gdbAdapter->state() != QProcess::Running) {
|
||||||
emit gdbInputAvailable(LogInput, cmd.command);
|
emit gdbInputAvailable(LogInput, cmd.command);
|
||||||
debugMessage(_("GDB PROCESS NOT RUNNING, PLAIN CMD IGNORED: ") + cmd.command);
|
debugMessage(_("GDB PROCESS NOT RUNNING, PLAIN CMD IGNORED: ") + cmd.command);
|
||||||
@@ -834,7 +823,9 @@ void GdbEngine::handleResultRecord(const GdbResultRecord &record)
|
|||||||
// << "\n data: " << record.data.toString(true);
|
// << "\n data: " << record.data.toString(true);
|
||||||
|
|
||||||
if (cmd.callback)
|
if (cmd.callback)
|
||||||
(this->*(cmd.callback))(record, cmd.cookie);
|
(this->*cmd.callback)(record, cmd.cookie);
|
||||||
|
if (cmd.adapterCallback)
|
||||||
|
(m_gdbAdapter->*cmd.adapterCallback)(record, cmd.cookie);
|
||||||
|
|
||||||
if (cmd.flags & RebuildModel) {
|
if (cmd.flags & RebuildModel) {
|
||||||
--m_pendingRequests;
|
--m_pendingRequests;
|
||||||
@@ -855,10 +846,13 @@ void GdbEngine::handleResultRecord(const GdbResultRecord &record)
|
|||||||
// An optimization would be requesting the continue immediately when the
|
// An optimization would be requesting the continue immediately when the
|
||||||
// event loop is entered, and let individual commands have a flag to suppress
|
// event loop is entered, and let individual commands have a flag to suppress
|
||||||
// that behavior.
|
// that behavior.
|
||||||
if (m_cookieForToken.isEmpty() && m_autoContinue) {
|
if (m_continuationAfterDone && m_cookieForToken.isEmpty()) {
|
||||||
m_autoContinue = false;
|
Continuation cont = m_continuationAfterDone;
|
||||||
continueInferior();
|
m_continuationAfterDone = 0;
|
||||||
showStatusMessage(tr("Continuing after temporary stop."));
|
(this->*cont)();
|
||||||
|
//showStatusMessage(tr("Continuing after temporary stop."));
|
||||||
|
} else {
|
||||||
|
PENDING_DEBUG("MISSING TOKENS: " << m_cookieForToken.keys());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1077,7 +1071,7 @@ void GdbEngine::handleAqcuiredInferior()
|
|||||||
|
|
||||||
void GdbEngine::handleAsyncOutput(const GdbMi &data)
|
void GdbEngine::handleAsyncOutput(const GdbMi &data)
|
||||||
{
|
{
|
||||||
const QByteArray &reason = data.findChild("reason").data();
|
const QByteArray reason = data.findChild("reason").data();
|
||||||
|
|
||||||
if (isExitedReason(reason)) {
|
if (isExitedReason(reason)) {
|
||||||
qq->notifyInferiorExited();
|
qq->notifyInferiorExited();
|
||||||
@@ -1107,7 +1101,7 @@ void GdbEngine::handleAsyncOutput(const GdbMi &data)
|
|||||||
|
|
||||||
qq->notifyInferiorStopped();
|
qq->notifyInferiorStopped();
|
||||||
handleAqcuiredInferior();
|
handleAqcuiredInferior();
|
||||||
m_autoContinue = true;
|
// FIXME: m_continuationAfterDone = true;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1123,7 +1117,7 @@ void GdbEngine::handleAsyncOutput(const GdbMi &data)
|
|||||||
flushCommand(cmd);
|
flushCommand(cmd);
|
||||||
}
|
}
|
||||||
showStatusMessage(tr("Processing queued commands."));
|
showStatusMessage(tr("Processing queued commands."));
|
||||||
m_autoContinue = true;
|
// FIXME: m_continuationAfterDone = true;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1185,64 +1179,12 @@ void GdbEngine::handleAsyncOutput(const GdbMi &data)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (isStoppedReason(reason) || reason.isEmpty()) {
|
if (isStoppedReason(reason) || reason.isEmpty()) {
|
||||||
if (m_modulesListOutdated) {
|
|
||||||
reloadModules();
|
|
||||||
m_modulesListOutdated = false;
|
|
||||||
}
|
|
||||||
// Need another round trip
|
|
||||||
if (reason == "breakpoint-hit") {
|
|
||||||
showStatusMessage(tr("Stopped at breakpoint."));
|
|
||||||
GdbMi frame = data.findChild("frame");
|
|
||||||
//debugMessage(_("HIT BREAKPOINT: " + frame.toString()));
|
|
||||||
m_currentFrame = _(frame.findChild("addr").data() + '%' +
|
|
||||||
frame.findChild("func").data() + '%');
|
|
||||||
|
|
||||||
if (theDebuggerAction(ListSourceFiles)->value().toBool())
|
|
||||||
reloadSourceFiles();
|
|
||||||
postCommand(_("-break-list"), CB(handleBreakList));
|
|
||||||
QVariant var = QVariant::fromValue<GdbMi>(data);
|
QVariant var = QVariant::fromValue<GdbMi>(data);
|
||||||
postCommand(_("p 0"), CB(handleAsyncOutput2), var); // dummy
|
if (m_debuggingHelperState == DebuggingHelperUninitialized) {
|
||||||
|
tryLoadDebuggingHelpers();
|
||||||
|
postCommand(_("p 4"), CB(handleStop1), var); // dummy
|
||||||
} else {
|
} else {
|
||||||
#ifdef Q_OS_LINUX
|
handleStop1(GdbResultRecord(), var);
|
||||||
// For some reason, attaching to a stopped process causes *two* stops
|
|
||||||
// when trying to continue (kernel 2.6.24-23-ubuntu).
|
|
||||||
// Interestingly enough, on MacOSX no signal is delivered at all.
|
|
||||||
if (reason == "signal-received"
|
|
||||||
&& data.findChild("signal-name").data() == "SIGSTOP") {
|
|
||||||
GdbMi frameData = data.findChild("frame");
|
|
||||||
if (frameData.findChild("func").data() == "_start"
|
|
||||||
&& frameData.findChild("from").data() == "/lib/ld-linux.so.2") {
|
|
||||||
postCommand(_("-exec-continue"), CB(handleExecContinue));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
if (reason == "signal-received"
|
|
||||||
&& theDebuggerBoolSetting(UseMessageBoxForSignals)) {
|
|
||||||
QByteArray name = data.findChild("signal-name").data();
|
|
||||||
// Ignore SIGTRAP as they are showing up regularily when
|
|
||||||
// stopping debugging.
|
|
||||||
if (name != "SIGTRAP") {
|
|
||||||
QByteArray meaning = data.findChild("signal-meaning").data();
|
|
||||||
QString msg = tr("<p>The inferior stopped because it received a "
|
|
||||||
"signal from the Operating System.<p>"
|
|
||||||
"<table><tr><td>Signal name : </td><td>%1</td></tr>"
|
|
||||||
"<tr><td>Signal meaning : </td><td>%2</td></tr></table>")
|
|
||||||
.arg(name.isEmpty() ? tr(" <Unknown> ") : _(name))
|
|
||||||
.arg(meaning.isEmpty() ? tr(" <Unknown> ") : _(meaning));
|
|
||||||
QMessageBox *mb = new QMessageBox(QMessageBox::Information,
|
|
||||||
tr("Signal received"), msg, QMessageBox::NoButton,
|
|
||||||
mainWindow());
|
|
||||||
mb->setAttribute(Qt::WA_DeleteOnClose);
|
|
||||||
mb->show();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (reason.isEmpty())
|
|
||||||
showStatusMessage(tr("Stopped."));
|
|
||||||
else
|
|
||||||
showStatusMessage(tr("Stopped: \"%1\"").arg(_(reason)));
|
|
||||||
handleAsyncOutput2(data);
|
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -1296,12 +1238,77 @@ void GdbEngine::reloadStack()
|
|||||||
postCommand(cmd, WatchUpdate, CB(handleStackListFrames), false);
|
postCommand(cmd, WatchUpdate, CB(handleStackListFrames), false);
|
||||||
}
|
}
|
||||||
|
|
||||||
void GdbEngine::handleAsyncOutput2(const GdbResultRecord &, const QVariant &cookie)
|
void GdbEngine::handleStop1(const GdbResultRecord &, const QVariant &cookie)
|
||||||
{
|
{
|
||||||
handleAsyncOutput2(cookie.value<GdbMi>());
|
GdbMi data = cookie.value<GdbMi>();
|
||||||
|
QByteArray reason = data.findChild("reason").data();
|
||||||
|
if (m_modulesListOutdated) {
|
||||||
|
reloadModules();
|
||||||
|
m_modulesListOutdated = false;
|
||||||
|
}
|
||||||
|
// Need another round trip
|
||||||
|
if (reason == "breakpoint-hit") {
|
||||||
|
showStatusMessage(tr("Stopped at breakpoint."));
|
||||||
|
GdbMi frame = data.findChild("frame");
|
||||||
|
//debugMessage(_("HIT BREAKPOINT: " + frame.toString()));
|
||||||
|
m_currentFrame = _(frame.findChild("addr").data() + '%' +
|
||||||
|
frame.findChild("func").data() + '%');
|
||||||
|
|
||||||
|
if (theDebuggerAction(ListSourceFiles)->value().toBool())
|
||||||
|
reloadSourceFiles();
|
||||||
|
postCommand(_("-break-list"), CB(handleBreakList));
|
||||||
|
QVariant var = QVariant::fromValue<GdbMi>(data);
|
||||||
|
postCommand(_("p 0"), CB(handleStop2), var); // dummy
|
||||||
|
} else {
|
||||||
|
#ifdef Q_OS_LINUX
|
||||||
|
// For some reason, attaching to a stopped process causes *two* stops
|
||||||
|
// when trying to continue (kernel 2.6.24-23-ubuntu).
|
||||||
|
// Interestingly enough, on MacOSX no signal is delivered at all.
|
||||||
|
if (reason == "signal-received"
|
||||||
|
&& data.findChild("signal-name").data() == "SIGSTOP") {
|
||||||
|
GdbMi frameData = data.findChild("frame");
|
||||||
|
if (frameData.findChild("func").data() == "_start"
|
||||||
|
&& frameData.findChild("from").data() == "/lib/ld-linux.so.2") {
|
||||||
|
postCommand(_("-exec-continue"), CB(handleExecContinue));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
if (reason == "signal-received"
|
||||||
|
&& theDebuggerBoolSetting(UseMessageBoxForSignals)) {
|
||||||
|
QByteArray name = data.findChild("signal-name").data();
|
||||||
|
// Ignore SIGTRAP as they are showing up regularily when
|
||||||
|
// stopping debugging.
|
||||||
|
if (name != "SIGTRAP") {
|
||||||
|
QByteArray meaning = data.findChild("signal-meaning").data();
|
||||||
|
QString msg = tr("<p>The inferior stopped because it received a "
|
||||||
|
"signal from the Operating System.<p>"
|
||||||
|
"<table><tr><td>Signal name : </td><td>%1</td></tr>"
|
||||||
|
"<tr><td>Signal meaning : </td><td>%2</td></tr></table>")
|
||||||
|
.arg(name.isEmpty() ? tr(" <Unknown> ") : _(name))
|
||||||
|
.arg(meaning.isEmpty() ? tr(" <Unknown> ") : _(meaning));
|
||||||
|
QMessageBox *mb = new QMessageBox(QMessageBox::Information,
|
||||||
|
tr("Signal received"), msg, QMessageBox::NoButton,
|
||||||
|
mainWindow());
|
||||||
|
mb->setAttribute(Qt::WA_DeleteOnClose);
|
||||||
|
mb->show();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (reason.isEmpty())
|
||||||
|
showStatusMessage(tr("Stopped."));
|
||||||
|
else
|
||||||
|
showStatusMessage(tr("Stopped: \"%1\"").arg(_(reason)));
|
||||||
|
handleStop2(data);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void GdbEngine::handleAsyncOutput2(const GdbMi &data)
|
void GdbEngine::handleStop2(const GdbResultRecord &, const QVariant &cookie)
|
||||||
|
{
|
||||||
|
handleStop2(cookie.value<GdbMi>());
|
||||||
|
}
|
||||||
|
|
||||||
|
void GdbEngine::handleStop2(const GdbMi &data)
|
||||||
{
|
{
|
||||||
qq->notifyInferiorStopped();
|
qq->notifyInferiorStopped();
|
||||||
|
|
||||||
@@ -1399,6 +1406,7 @@ void GdbEngine::handleFileExecAndSymbols(const GdbResultRecord &response, const
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if 0
|
||||||
void GdbEngine::handleExecRun(const GdbResultRecord &response, const QVariant &)
|
void GdbEngine::handleExecRun(const GdbResultRecord &response, const QVariant &)
|
||||||
{
|
{
|
||||||
if (response.resultClass == GdbResultRunning) {
|
if (response.resultClass == GdbResultRunning) {
|
||||||
@@ -1413,6 +1421,7 @@ void GdbEngine::handleExecRun(const GdbResultRecord &response, const QVariant &)
|
|||||||
qq->notifyInferiorExited();
|
qq->notifyInferiorExited();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
void GdbEngine::handleExecContinue(const GdbResultRecord &response, const QVariant &)
|
void GdbEngine::handleExecContinue(const GdbResultRecord &response, const QVariant &)
|
||||||
{
|
{
|
||||||
@@ -1519,6 +1528,7 @@ void GdbEngine::handleExitHelper(const GdbResultRecord &, const QVariant &)
|
|||||||
|
|
||||||
void GdbEngine::exitDebugger2()
|
void GdbEngine::exitDebugger2()
|
||||||
{
|
{
|
||||||
|
/*
|
||||||
postCommand(_("-gdb-exit"), CB(handleExit));
|
postCommand(_("-gdb-exit"), CB(handleExit));
|
||||||
// 20s can easily happen when loading webkit debug information
|
// 20s can easily happen when loading webkit debug information
|
||||||
if (!m_gdbAdapter->waitForFinished(20000)) {
|
if (!m_gdbAdapter->waitForFinished(20000)) {
|
||||||
@@ -1533,6 +1543,7 @@ void GdbEngine::exitDebugger2()
|
|||||||
.arg(m_gdbAdapter->state()));
|
.arg(m_gdbAdapter->state()));
|
||||||
m_gdbAdapter->kill();
|
m_gdbAdapter->kill();
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
m_outputCollector.shutdown();
|
m_outputCollector.shutdown();
|
||||||
initializeVariables();
|
initializeVariables();
|
||||||
@@ -1548,6 +1559,8 @@ int GdbEngine::currentFrame() const
|
|||||||
void GdbEngine::startDebugger(const DebuggerStartParametersPtr &sp)
|
void GdbEngine::startDebugger(const DebuggerStartParametersPtr &sp)
|
||||||
{
|
{
|
||||||
m_startParameters = sp;
|
m_startParameters = sp;
|
||||||
|
m_gdbAdapter->startAdapter(sp);
|
||||||
|
/*
|
||||||
// This should be set by the constructor or in exitDebugger().
|
// This should be set by the constructor or in exitDebugger().
|
||||||
QTC_ASSERT(m_debuggingHelperState == DebuggingHelperUninitialized,
|
QTC_ASSERT(m_debuggingHelperState == DebuggingHelperUninitialized,
|
||||||
initializeVariables());
|
initializeVariables());
|
||||||
@@ -1619,154 +1632,7 @@ void GdbEngine::startDebugger(const DebuggerStartParametersPtr &sp)
|
|||||||
QString loc = theDebuggerStringSetting(GdbLocation);
|
QString loc = theDebuggerStringSetting(GdbLocation);
|
||||||
showStatusMessage(tr("Starting Debugger: ") + loc + _c(' ') + gdbArgs.join(_(" ")));
|
showStatusMessage(tr("Starting Debugger: ") + loc + _c(' ') + gdbArgs.join(_(" ")));
|
||||||
m_gdbAdapter->start(loc, gdbArgs);
|
m_gdbAdapter->start(loc, gdbArgs);
|
||||||
}
|
*/
|
||||||
|
|
||||||
void GdbEngine::emitStartFailed()
|
|
||||||
{
|
|
||||||
// QMessageBox::critical(mainWindow(), tr("Debugger Startup Failure"),
|
|
||||||
// tr("Cannot start debugger: %1").arg(m_gdbAdapter->errorString()));
|
|
||||||
m_outputCollector.shutdown();
|
|
||||||
m_stubProc.blockSignals(true);
|
|
||||||
m_stubProc.stop();
|
|
||||||
m_stubProc.blockSignals(false);
|
|
||||||
emit startFailed();
|
|
||||||
}
|
|
||||||
|
|
||||||
void GdbEngine::startDebugger2()
|
|
||||||
{
|
|
||||||
debugMessage(_("STARTUP, PHASE 2"));
|
|
||||||
showStatusMessage(tr("Gdb Running..."));
|
|
||||||
|
|
||||||
postCommand(_("show version"), CB(handleShowVersion));
|
|
||||||
//postCommand(_("-enable-timings");
|
|
||||||
postCommand(_("set print static-members off")); // Seemingly doesn't work.
|
|
||||||
//postCommand(_("set debug infrun 1"));
|
|
||||||
//postCommand(_("define hook-stop\n-thread-list-ids\n-stack-list-frames\nend"));
|
|
||||||
//postCommand(_("define hook-stop\nprint 4\nend"));
|
|
||||||
//postCommand(_("define hookpost-stop\nprint 5\nend"));
|
|
||||||
//postCommand(_("define hook-call\nprint 6\nend"));
|
|
||||||
//postCommand(_("define hookpost-call\nprint 7\nend"));
|
|
||||||
//postCommand(_("set print object on")); // works with CLI, but not MI
|
|
||||||
//postCommand(_("set step-mode on")); // we can't work with that yes
|
|
||||||
//postCommand(_("set exec-done-display on"));
|
|
||||||
//postCommand(_("set print pretty on"));
|
|
||||||
//postCommand(_("set confirm off"));
|
|
||||||
//postCommand(_("set pagination off"));
|
|
||||||
postCommand(_("set print inferior-events 1"));
|
|
||||||
postCommand(_("set breakpoint pending on"));
|
|
||||||
postCommand(_("set print elements 10000"));
|
|
||||||
postCommand(_("-data-list-register-names"), CB(handleRegisterListNames));
|
|
||||||
|
|
||||||
//postCommand(_("set substitute-path /var/tmp/qt-x11-src-4.5.0 "
|
|
||||||
// "/home/sandbox/qtsdk-2009.01/qt"));
|
|
||||||
|
|
||||||
// one of the following is needed to prevent crashes in gdb on code like:
|
|
||||||
// template <class T> T foo() { return T(0); }
|
|
||||||
// int main() { return foo<int>(); }
|
|
||||||
// (gdb) call 'int foo<int>'()
|
|
||||||
// /build/buildd/gdb-6.8/gdb/valops.c:2069: internal-error:
|
|
||||||
postCommand(_("set overload-resolution off"));
|
|
||||||
//postCommand(_("set demangle-style none"));
|
|
||||||
|
|
||||||
// From the docs:
|
|
||||||
// Stop means reenter debugger if this signal happens (implies print).
|
|
||||||
// Print means print a message if this signal happens.
|
|
||||||
// Pass means let program see this signal;
|
|
||||||
// otherwise program doesn't know.
|
|
||||||
// Pass and Stop may be combined.
|
|
||||||
// We need "print" as otherwise we would get no feedback whatsoever
|
|
||||||
// Custom DebuggingHelper crashs which happen regularily for when accessing
|
|
||||||
// uninitialized variables.
|
|
||||||
postCommand(_("handle SIGSEGV nopass stop print"));
|
|
||||||
|
|
||||||
// This is useful to kill the inferior whenever gdb dies.
|
|
||||||
//postCommand(_("handle SIGTERM pass nostop print"));
|
|
||||||
|
|
||||||
postCommand(_("set unwindonsignal on"));
|
|
||||||
//postCommand(_("pwd"));
|
|
||||||
postCommand(_("set width 0"));
|
|
||||||
postCommand(_("set height 0"));
|
|
||||||
|
|
||||||
#ifdef Q_OS_MAC
|
|
||||||
postCommand(_("-gdb-set inferior-auto-start-cfm off"));
|
|
||||||
postCommand(_("-gdb-set sharedLibrary load-rules "
|
|
||||||
"dyld \".*libSystem.*\" all "
|
|
||||||
"dyld \".*libauto.*\" all "
|
|
||||||
"dyld \".*AppKit.*\" all "
|
|
||||||
"dyld \".*PBGDBIntrospectionSupport.*\" all "
|
|
||||||
"dyld \".*Foundation.*\" all "
|
|
||||||
"dyld \".*CFDataFormatters.*\" all "
|
|
||||||
"dyld \".*libobjc.*\" all "
|
|
||||||
"dyld \".*CarbonDataFormatters.*\" all"));
|
|
||||||
#endif
|
|
||||||
|
|
||||||
QString scriptFileName = theDebuggerStringSetting(GdbScriptFile);
|
|
||||||
if (!scriptFileName.isEmpty()) {
|
|
||||||
if (QFileInfo(scriptFileName).isReadable()) {
|
|
||||||
postCommand(_("source ") + scriptFileName);
|
|
||||||
} else {
|
|
||||||
QMessageBox::warning(mainWindow(),
|
|
||||||
tr("Cannot find debugger initialization script"),
|
|
||||||
tr("The debugger settings point to a script file at '%1' "
|
|
||||||
"which is not accessible. If a script file is not needed, "
|
|
||||||
"consider clearing that entry to avoid this warning. "
|
|
||||||
).arg(scriptFileName));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (startMode() == AttachExternal || startMode() == AttachCrashedExternal) {
|
|
||||||
postCommand(_("attach %1").arg(m_startParameters->attachPID), CB(handleAttach));
|
|
||||||
// Task 254674 does not want to remove them
|
|
||||||
//qq->breakHandler()->removeAllBreakpoints();
|
|
||||||
} else if (startMode() == AttachCore) {
|
|
||||||
QFileInfo fi(m_startParameters->executable);
|
|
||||||
QString fileName = _c('"') + fi.absoluteFilePath() + _c('"');
|
|
||||||
QFileInfo fi2(m_startParameters->coreFile);
|
|
||||||
// quoting core name below fails in gdb 6.8-debian
|
|
||||||
QString coreName = fi2.absoluteFilePath();
|
|
||||||
postCommand(_("-file-exec-and-symbols ") + fileName, CB(handleFileExecAndSymbols));
|
|
||||||
postCommand(_("target core ") + coreName, CB(handleTargetCore));
|
|
||||||
qq->breakHandler()->removeAllBreakpoints();
|
|
||||||
} else if (startMode() == StartRemote) {
|
|
||||||
postCommand(_("set architecture %1").arg(m_startParameters->remoteArchitecture));
|
|
||||||
qq->breakHandler()->setAllPending();
|
|
||||||
//QFileInfo fi(m_startParameters->executable);
|
|
||||||
//QString fileName = fi.absoluteFileName();
|
|
||||||
QString fileName = m_startParameters->executable;
|
|
||||||
postCommand(_("-file-exec-and-symbols \"%1\"").arg(fileName), CB(handleFileExecAndSymbols));
|
|
||||||
// works only for > 6.8
|
|
||||||
postCommand(_("set target-async on"), CB(handleSetTargetAsync));
|
|
||||||
} else if (m_startParameters->useTerminal) {
|
|
||||||
qq->breakHandler()->setAllPending();
|
|
||||||
} else if (startMode() == StartInternal || startMode() == StartExternal) {
|
|
||||||
qq->breakHandler()->setAllPending();
|
|
||||||
m_gdbAdapter->attach();
|
|
||||||
if (m_gdbAdapter->isAdapter()) {
|
|
||||||
m_autoContinue = true;
|
|
||||||
qq->notifyInferiorStopped();
|
|
||||||
attemptBreakpointSynchronization();
|
|
||||||
qq->notifyInferiorRunningRequested();
|
|
||||||
} else {
|
|
||||||
#ifdef Q_OS_MAC
|
|
||||||
postCommand(_("sharedlibrary apply-load-rules all"));
|
|
||||||
#endif
|
|
||||||
if (!m_startParameters->processArgs.isEmpty())
|
|
||||||
postCommand(_("-exec-arguments ") + m_startParameters->processArgs.join(_(" ")));
|
|
||||||
#ifdef Q_OS_MAC
|
|
||||||
// On MacOS, breaking in at the entry point wreaks havoc.
|
|
||||||
postCommand(_("tbreak main"));
|
|
||||||
m_waitingForFirstBreakpointToBeHit = true;
|
|
||||||
qq->notifyInferiorRunningRequested();
|
|
||||||
postCommand(_("-exec-run"), CB(handleExecRun));
|
|
||||||
#else
|
|
||||||
if (!m_dumperInjectionLoad)
|
|
||||||
postCommand(_("set auto-solib-add off"));
|
|
||||||
postCommand(_("info target"), CB(handleStart));
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
emit startSuccessful();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void GdbEngine::continueInferior()
|
void GdbEngine::continueInferior()
|
||||||
@@ -1777,32 +1643,6 @@ void GdbEngine::continueInferior()
|
|||||||
postCommand(_("-exec-continue"), CB(handleExecContinue));
|
postCommand(_("-exec-continue"), CB(handleExecContinue));
|
||||||
}
|
}
|
||||||
|
|
||||||
void GdbEngine::handleStart(const GdbResultRecord &response, const QVariant &)
|
|
||||||
{
|
|
||||||
#if defined(Q_OS_MAC)
|
|
||||||
Q_UNUSED(response)
|
|
||||||
#else
|
|
||||||
if (response.resultClass == GdbResultDone) {
|
|
||||||
// [some leading stdout here]
|
|
||||||
// >&" Entry point: 0x80831f0 0x08048134 - 0x08048147 is .interp\n"
|
|
||||||
// [some trailing stdout here]
|
|
||||||
QString msg = _(response.data.findChild("consolestreamoutput").data());
|
|
||||||
QRegExp needle(_("\\bEntry point: (0x[0-9a-f]+)\\b"));
|
|
||||||
if (needle.indexIn(msg) != -1) {
|
|
||||||
//debugMessage(_("STREAM: ") + msg + " " + needle.cap(1));
|
|
||||||
postCommand(_("tbreak *") + needle.cap(1));
|
|
||||||
m_waitingForFirstBreakpointToBeHit = true;
|
|
||||||
qq->notifyInferiorRunningRequested();
|
|
||||||
postCommand(_("-exec-run"), CB(handleExecRun));
|
|
||||||
} else {
|
|
||||||
debugMessage(_("PARSING START ADDRESS FAILED: ") + msg);
|
|
||||||
}
|
|
||||||
} else if (response.resultClass == GdbResultError) {
|
|
||||||
debugMessage(_("FETCHING START ADDRESS FAILED: " + response.toString()));
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
void GdbEngine::handleAttach(const GdbResultRecord &, const QVariant &)
|
void GdbEngine::handleAttach(const GdbResultRecord &, const QVariant &)
|
||||||
{
|
{
|
||||||
qq->notifyInferiorStopped();
|
qq->notifyInferiorStopped();
|
||||||
@@ -1850,7 +1690,7 @@ void GdbEngine::handleTargetRemote(const GdbResultRecord &record, const QVariant
|
|||||||
if (record.resultClass == GdbResultDone) {
|
if (record.resultClass == GdbResultDone) {
|
||||||
//postCommand(_("-exec-continue"), CB(handleExecContinue));
|
//postCommand(_("-exec-continue"), CB(handleExecContinue));
|
||||||
handleAqcuiredInferior();
|
handleAqcuiredInferior();
|
||||||
m_autoContinue = true;
|
// FIXME m_continuationAfterDone = true;
|
||||||
} else if (record.resultClass == GdbResultError) {
|
} else if (record.resultClass == GdbResultError) {
|
||||||
// 16^error,msg="hd:5555: Connection timed out."
|
// 16^error,msg="hd:5555: Connection timed out."
|
||||||
QString msg = __(record.data.findChild("msg").data());
|
QString msg = __(record.data.findChild("msg").data());
|
||||||
@@ -1899,8 +1739,15 @@ void GdbEngine::nextExec()
|
|||||||
qq->notifyInferiorRunningRequested();
|
qq->notifyInferiorRunningRequested();
|
||||||
if (qq->isReverseDebugging())
|
if (qq->isReverseDebugging())
|
||||||
postCommand(_("-reverse-next"), CB(handleExecContinue));
|
postCommand(_("-reverse-next"), CB(handleExecContinue));
|
||||||
else
|
else {
|
||||||
|
#if 0
|
||||||
postCommand(_("-exec-next"), CB(handleExecContinue));
|
postCommand(_("-exec-next"), CB(handleExecContinue));
|
||||||
|
#else
|
||||||
|
postCommand(_("tbreak %1:%2").arg(QFileInfo(lastFile).fileName())
|
||||||
|
.arg(lastLine + 1));
|
||||||
|
postCommand(_("-exec-continue"), CB(handleExecContinue));
|
||||||
|
#endif
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void GdbEngine::nextIExec()
|
void GdbEngine::nextIExec()
|
||||||
@@ -3478,7 +3325,7 @@ void GdbEngine::handleDebuggingHelperValue1(const GdbResultRecord &record,
|
|||||||
&& msg.startsWith(__("The program being debugged stopped while"))
|
&& msg.startsWith(__("The program being debugged stopped while"))
|
||||||
&& msg.contains(__("qDumpObjectData440"))) {
|
&& msg.contains(__("qDumpObjectData440"))) {
|
||||||
// Fake full stop
|
// Fake full stop
|
||||||
postCommand(_("p 0"), CB(handleAsyncOutput2)); // dummy
|
postCommand(_("p 0"), CB(handleStop2)); // dummy
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
@@ -4287,14 +4134,209 @@ void GdbEngine::handleFetchDisassemblerByAddress0(const GdbResultRecord &record,
|
|||||||
|
|
||||||
void GdbEngine::gotoLocation(const StackFrame &frame, bool setMarker)
|
void GdbEngine::gotoLocation(const StackFrame &frame, bool setMarker)
|
||||||
{
|
{
|
||||||
|
lastFile = frame.file;
|
||||||
|
lastLine = frame.line;
|
||||||
m_manager->gotoLocation(frame, setMarker);
|
m_manager->gotoLocation(frame, setMarker);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Starting up & shutting down
|
||||||
|
//
|
||||||
|
|
||||||
|
void GdbEngine::handleAdapterStartFailed(const QString &msg)
|
||||||
|
{
|
||||||
|
debugMessage(_("ADAPTER START FAILED"));
|
||||||
|
m_outputCollector.shutdown();
|
||||||
|
QMessageBox::critical(mainWindow(), tr("Error"), msg);
|
||||||
|
QTC_ASSERT(status() == DebuggerInferiorRunning, /**/);
|
||||||
|
//interruptInferior();
|
||||||
|
}
|
||||||
|
|
||||||
|
void GdbEngine::handleAdapterStarted()
|
||||||
|
{
|
||||||
|
debugMessage(_("ADAPTER SUCCESSFULLY STARTED, PREPARING INFERIOR"));
|
||||||
|
m_gdbAdapter->prepareInferior();
|
||||||
|
}
|
||||||
|
|
||||||
|
void GdbEngine::handleInferiorPreparationFailed(const QString &msg)
|
||||||
|
{
|
||||||
|
debugMessage(_("INFERIOR PREPARATION FAILD"));
|
||||||
|
m_outputCollector.shutdown();
|
||||||
|
QMessageBox::critical(mainWindow(), tr("Error"),
|
||||||
|
tr("Inferior start preparation failed:\n") + msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
void GdbEngine::handleInferiorPrepared()
|
||||||
|
{
|
||||||
|
// FIXME: Check that inferior is in "stopped" state
|
||||||
|
qq->notifyInferiorStopped();
|
||||||
|
showStatusMessage(tr("Inferior prepared for startup."));
|
||||||
|
|
||||||
|
postCommand(_("show version"), CB(handleShowVersion));
|
||||||
|
//postCommand(_("-enable-timings");
|
||||||
|
postCommand(_("set print static-members off")); // Seemingly doesn't work.
|
||||||
|
//postCommand(_("set debug infrun 1"));
|
||||||
|
//postCommand(_("define hook-stop\n-thread-list-ids\n-stack-list-frames\nend"));
|
||||||
|
//postCommand(_("define hook-stop\nprint 4\nend"));
|
||||||
|
//postCommand(_("define hookpost-stop\nprint 5\nend"));
|
||||||
|
//postCommand(_("define hook-call\nprint 6\nend"));
|
||||||
|
//postCommand(_("define hookpost-call\nprint 7\nend"));
|
||||||
|
//postCommand(_("set print object on")); // works with CLI, but not MI
|
||||||
|
//postCommand(_("set step-mode on")); // we can't work with that yes
|
||||||
|
//postCommand(_("set exec-done-display on"));
|
||||||
|
//postCommand(_("set print pretty on"));
|
||||||
|
//postCommand(_("set confirm off"));
|
||||||
|
//postCommand(_("set pagination off"));
|
||||||
|
postCommand(_("set print inferior-events 1"));
|
||||||
|
postCommand(_("set breakpoint pending on"));
|
||||||
|
postCommand(_("set print elements 10000"));
|
||||||
|
postCommand(_("-data-list-register-names"), CB(handleRegisterListNames));
|
||||||
|
|
||||||
|
//postCommand(_("set substitute-path /var/tmp/qt-x11-src-4.5.0 "
|
||||||
|
// "/home/sandbox/qtsdk-2009.01/qt"));
|
||||||
|
|
||||||
|
// one of the following is needed to prevent crashes in gdb on code like:
|
||||||
|
// template <class T> T foo() { return T(0); }
|
||||||
|
// int main() { return foo<int>(); }
|
||||||
|
// (gdb) call 'int foo<int>'()
|
||||||
|
// /build/buildd/gdb-6.8/gdb/valops.c:2069: internal-error:
|
||||||
|
postCommand(_("set overload-resolution off"));
|
||||||
|
//postCommand(_("set demangle-style none"));
|
||||||
|
|
||||||
|
// From the docs:
|
||||||
|
// Stop means reenter debugger if this signal happens (implies print).
|
||||||
|
// Print means print a message if this signal happens.
|
||||||
|
// Pass means let program see this signal;
|
||||||
|
// otherwise program doesn't know.
|
||||||
|
// Pass and Stop may be combined.
|
||||||
|
// We need "print" as otherwise we would get no feedback whatsoever
|
||||||
|
// Custom DebuggingHelper crashs which happen regularily for when accessing
|
||||||
|
// uninitialized variables.
|
||||||
|
postCommand(_("handle SIGSEGV nopass stop print"));
|
||||||
|
|
||||||
|
// This is useful to kill the inferior whenever gdb dies.
|
||||||
|
//postCommand(_("handle SIGTERM pass nostop print"));
|
||||||
|
|
||||||
|
postCommand(_("set unwindonsignal on"));
|
||||||
|
//postCommand(_("pwd"));
|
||||||
|
postCommand(_("set width 0"));
|
||||||
|
postCommand(_("set height 0"));
|
||||||
|
|
||||||
|
#ifdef Q_OS_MAC
|
||||||
|
postCommand(_("-gdb-set inferior-auto-start-cfm off"));
|
||||||
|
postCommand(_("-gdb-set sharedLibrary load-rules "
|
||||||
|
"dyld \".*libSystem.*\" all "
|
||||||
|
"dyld \".*libauto.*\" all "
|
||||||
|
"dyld \".*AppKit.*\" all "
|
||||||
|
"dyld \".*PBGDBIntrospectionSupport.*\" all "
|
||||||
|
"dyld \".*Foundation.*\" all "
|
||||||
|
"dyld \".*CFDataFormatters.*\" all "
|
||||||
|
"dyld \".*libobjc.*\" all "
|
||||||
|
"dyld \".*CarbonDataFormatters.*\" all"));
|
||||||
|
#endif
|
||||||
|
|
||||||
|
QString scriptFileName = theDebuggerStringSetting(GdbScriptFile);
|
||||||
|
if (!scriptFileName.isEmpty()) {
|
||||||
|
if (QFileInfo(scriptFileName).isReadable()) {
|
||||||
|
postCommand(_("source ") + scriptFileName);
|
||||||
|
} else {
|
||||||
|
QMessageBox::warning(mainWindow(),
|
||||||
|
tr("Cannot find debugger initialization script"),
|
||||||
|
tr("The debugger settings point to a script file at '%1' "
|
||||||
|
"which is not accessible. If a script file is not needed, "
|
||||||
|
"consider clearing that entry to avoid this warning. "
|
||||||
|
).arg(scriptFileName));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
if (startMode() == AttachExternal || startMode() == AttachCrashedExternal) {
|
||||||
|
postCommand(_("attach %1").arg(m_startParameters->attachPID), CB(handleAttach));
|
||||||
|
// Task 254674 does not want to remove them
|
||||||
|
//qq->breakHandler()->removeAllBreakpoints();
|
||||||
|
} else if (startMode() == AttachCore) {
|
||||||
|
QFileInfo fi(m_startParameters->executable);
|
||||||
|
QString fileName = _c('"') + fi.absoluteFilePath() + _c('"');
|
||||||
|
QFileInfo fi2(m_startParameters->coreFile);
|
||||||
|
// quoting core name below fails in gdb 6.8-debian
|
||||||
|
QString coreName = fi2.absoluteFilePath();
|
||||||
|
postCommand(_("-file-exec-and-symbols ") + fileName, CB(handleFileExecAndSymbols));
|
||||||
|
postCommand(_("target core ") + coreName, CB(handleTargetCore));
|
||||||
|
qq->breakHandler()->removeAllBreakpoints();
|
||||||
|
} else if (startMode() == StartRemote) {
|
||||||
|
postCommand(_("set architecture %1").arg(m_startParameters->remoteArchitecture));
|
||||||
|
qq->breakHandler()->setAllPending();
|
||||||
|
//QFileInfo fi(m_startParameters->executable);
|
||||||
|
//QString fileName = fi.absoluteFileName();
|
||||||
|
QString fileName = m_startParameters->executable;
|
||||||
|
postCommand(_("-file-exec-and-symbols \"%1\"").arg(fileName), CB(handleFileExecAndSymbols));
|
||||||
|
// works only for > 6.8
|
||||||
|
postCommand(_("set target-async on"), CB(handleSetTargetAsync));
|
||||||
|
} else if (m_startParameters->useTerminal) {
|
||||||
|
qq->breakHandler()->setAllPending();
|
||||||
|
} else if (startMode() == StartInternal || startMode() == StartExternal) {
|
||||||
|
qq->breakHandler()->setAllPending();
|
||||||
|
m_gdbAdapter->attach();
|
||||||
|
if (m_gdbAdapter->isAdapter()) {
|
||||||
|
m_continuationAfterDone = true;
|
||||||
|
qq->notifyInferiorStopped();
|
||||||
|
attemptBreakpointSynchronization();
|
||||||
|
qq->notifyInferiorRunningRequested();
|
||||||
|
} [...]
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
// initial attempt to set breakpoints
|
||||||
|
QTC_ASSERT(m_continuationAfterDone == 0, /**/);
|
||||||
|
showStatusMessage(tr("Start initial breakpoint setting."));
|
||||||
|
m_continuationAfterDone = &GdbEngine::handleInitialBreakpointsSet;
|
||||||
|
attemptBreakpointSynchronization();
|
||||||
|
}
|
||||||
|
|
||||||
|
void GdbEngine::handleInitialBreakpointsSet()
|
||||||
|
{
|
||||||
|
showStatusMessage(tr("Finishing initial breakpoint setting."));
|
||||||
|
qq->notifyInferiorRunningRequested();
|
||||||
|
m_gdbAdapter->startInferior();
|
||||||
|
}
|
||||||
|
|
||||||
|
void GdbEngine::handleInferiorStartFailed(const QString &msg)
|
||||||
|
{
|
||||||
|
debugMessage(_("INFERIOR START FAILED"));
|
||||||
|
QMessageBox::critical(mainWindow(), tr("Error"),
|
||||||
|
tr("Inferior start failed:\n") + msg);
|
||||||
|
qq->notifyInferiorExited();
|
||||||
|
}
|
||||||
|
|
||||||
|
void GdbEngine::handleInferiorStarted()
|
||||||
|
{
|
||||||
|
qq->notifyInferiorRunning();
|
||||||
|
}
|
||||||
|
|
||||||
|
void GdbEngine::handleInferiorShutDown()
|
||||||
|
{
|
||||||
|
debugMessage(_("INFERIOR SUCCESSFULLY SHUT DOWN"));
|
||||||
|
}
|
||||||
|
|
||||||
|
void GdbEngine::handleInferiorShutdownFailed(const QString &msg)
|
||||||
|
{
|
||||||
|
debugMessage(_("INFERIOR SHUTDOWN FAILED"));
|
||||||
|
QMessageBox::critical(mainWindow(), tr("Error"),
|
||||||
|
tr("Inferior shutdown failed:\n") + msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Factory
|
||||||
|
//
|
||||||
|
|
||||||
IDebuggerEngine *createGdbEngine(DebuggerManager *parent,
|
IDebuggerEngine *createGdbEngine(DebuggerManager *parent,
|
||||||
QList<Core::IOptionsPage*> *opts)
|
QList<Core::IOptionsPage*> *opts)
|
||||||
{
|
{
|
||||||
opts->push_back(new GdbOptionsPage);
|
opts->push_back(new GdbOptionsPage);
|
||||||
return new GdbEngine(parent, new PlainGdbAdapter);
|
GdbEngine *engine = new GdbEngine(parent);
|
||||||
|
PlainGdbAdapter *adapter = new PlainGdbAdapter(engine);
|
||||||
|
engine->setGdbAdapter(adapter);
|
||||||
|
return engine;
|
||||||
}
|
}
|
||||||
|
|
||||||
IDebuggerEngine *createSymbianEngine(DebuggerManager *parent,
|
IDebuggerEngine *createSymbianEngine(DebuggerManager *parent,
|
||||||
@@ -4305,8 +4347,9 @@ IDebuggerEngine *createSymbianEngine(DebuggerManager *parent,
|
|||||||
|
|
||||||
if (!qgetenv("QTCREATOR_WITH_S60").isEmpty())
|
if (!qgetenv("QTCREATOR_WITH_S60").isEmpty())
|
||||||
opts->push_back(new TrkOptionsPage(options));
|
opts->push_back(new TrkOptionsPage(options));
|
||||||
TrkGdbAdapter *adapter = new TrkGdbAdapter(options);
|
GdbEngine *engine = new GdbEngine(parent);
|
||||||
GdbEngine *engine = new GdbEngine(parent, adapter);
|
TrkGdbAdapter *adapter = new TrkGdbAdapter(engine, options);
|
||||||
|
engine->setGdbAdapter(adapter);
|
||||||
QObject::connect(adapter, SIGNAL(output(QString)),
|
QObject::connect(adapter, SIGNAL(output(QString)),
|
||||||
parent, SLOT(showDebuggerOutput(QString)));
|
parent, SLOT(showDebuggerOutput(QString)));
|
||||||
return engine;
|
return engine;
|
||||||
|
|||||||
@@ -33,11 +33,8 @@
|
|||||||
#include "idebuggerengine.h"
|
#include "idebuggerengine.h"
|
||||||
#include "debuggermanager.h" // only for StartParameters
|
#include "debuggermanager.h" // only for StartParameters
|
||||||
#include "gdbmi.h"
|
#include "gdbmi.h"
|
||||||
#include "abstractgdbadapter.h"
|
|
||||||
#include "outputcollector.h"
|
|
||||||
#include "watchutils.h"
|
#include "watchutils.h"
|
||||||
|
#include "outputcollector.h"
|
||||||
#include <consoleprocess.h>
|
|
||||||
|
|
||||||
#include <QtCore/QByteArray>
|
#include <QtCore/QByteArray>
|
||||||
#include <QtCore/QHash>
|
#include <QtCore/QHash>
|
||||||
@@ -45,6 +42,7 @@
|
|||||||
#include <QtCore/QObject>
|
#include <QtCore/QObject>
|
||||||
#include <QtCore/QProcess>
|
#include <QtCore/QProcess>
|
||||||
#include <QtCore/QPoint>
|
#include <QtCore/QPoint>
|
||||||
|
#include <QtCore/QSet>
|
||||||
#include <QtCore/QTextCodec>
|
#include <QtCore/QTextCodec>
|
||||||
#include <QtCore/QTime>
|
#include <QtCore/QTime>
|
||||||
#include <QtCore/QVariant>
|
#include <QtCore/QVariant>
|
||||||
@@ -58,7 +56,7 @@ QT_END_NAMESPACE
|
|||||||
namespace Debugger {
|
namespace Debugger {
|
||||||
namespace Internal {
|
namespace Internal {
|
||||||
|
|
||||||
|
class AbstractGdbAdapter;
|
||||||
class DebuggerManager;
|
class DebuggerManager;
|
||||||
class IDebuggerManagerAccessForEngines;
|
class IDebuggerManagerAccessForEngines;
|
||||||
class GdbResultRecord;
|
class GdbResultRecord;
|
||||||
@@ -75,52 +73,14 @@ enum DebuggingHelperState
|
|||||||
DebuggingHelperUnavailable,
|
DebuggingHelperUnavailable,
|
||||||
};
|
};
|
||||||
|
|
||||||
class PlainGdbAdapter : public AbstractGdbAdapter
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
PlainGdbAdapter(QObject *parent = 0)
|
|
||||||
: AbstractGdbAdapter(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(started()),
|
|
||||||
this, SIGNAL(started()));
|
|
||||||
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); }
|
|
||||||
bool isAdapter() const { return false; }
|
|
||||||
void attach();
|
|
||||||
void interruptInferior();
|
|
||||||
|
|
||||||
private:
|
|
||||||
QProcess m_proc;
|
|
||||||
};
|
|
||||||
|
|
||||||
class GdbEngine : public IDebuggerEngine
|
class GdbEngine : public IDebuggerEngine
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
public:
|
public:
|
||||||
GdbEngine(DebuggerManager *parent, AbstractGdbAdapter *gdbAdapter);
|
explicit GdbEngine(DebuggerManager *parent);
|
||||||
~GdbEngine();
|
~GdbEngine();
|
||||||
|
void setGdbAdapter(AbstractGdbAdapter *adapter);
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void gdbInputAvailable(int channel, const QString &msg);
|
void gdbInputAvailable(int channel, const QString &msg);
|
||||||
@@ -145,7 +105,6 @@ private:
|
|||||||
void shutdown();
|
void shutdown();
|
||||||
void setToolTipExpression(const QPoint &mousePos, TextEditor::ITextEditor *editor, int cursorPos);
|
void setToolTipExpression(const QPoint &mousePos, TextEditor::ITextEditor *editor, int cursorPos);
|
||||||
void startDebugger(const DebuggerStartParametersPtr &sp);
|
void startDebugger(const DebuggerStartParametersPtr &sp);
|
||||||
Q_SLOT void startDebugger2();
|
|
||||||
void exitDebugger();
|
void exitDebugger();
|
||||||
void exitDebugger2();
|
void exitDebugger2();
|
||||||
void detachDebugger();
|
void detachDebugger();
|
||||||
@@ -217,14 +176,20 @@ public: // otherwise the Qt flag macros are unhappy
|
|||||||
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
typedef void (GdbEngine::*GdbCommandCallback)(const GdbResultRecord &record, const QVariant &cookie);
|
typedef void (GdbEngine::*GdbCommandCallback)
|
||||||
|
(const GdbResultRecord &record, const QVariant &cookie);
|
||||||
|
typedef void (AbstractGdbAdapter::*AdapterCallback)
|
||||||
|
(const GdbResultRecord &record, const QVariant &cookie);
|
||||||
|
|
||||||
struct GdbCommand
|
struct GdbCommand
|
||||||
{
|
{
|
||||||
GdbCommand() : flags(0), callback(0), callbackName(0) {}
|
GdbCommand()
|
||||||
|
: flags(0), callback(0), adapterCallback(0), callbackName(0)
|
||||||
|
{}
|
||||||
|
|
||||||
int flags;
|
int flags;
|
||||||
GdbCommandCallback callback;
|
GdbCommandCallback callback;
|
||||||
|
AdapterCallback adapterCallback;
|
||||||
const char *callbackName;
|
const char *callbackName;
|
||||||
QString command;
|
QString command;
|
||||||
QVariant cookie;
|
QVariant cookie;
|
||||||
@@ -235,7 +200,7 @@ private:
|
|||||||
// queue". resultNeeded == true increments m_pendingResults on
|
// queue". resultNeeded == true increments m_pendingResults on
|
||||||
// send and decrements on receipt, effectively preventing
|
// send and decrements on receipt, effectively preventing
|
||||||
// watch model updates before everything is finished.
|
// watch model updates before everything is finished.
|
||||||
void flushCommand(GdbCommand &cmd);
|
void flushCommand(const GdbCommand &cmd);
|
||||||
void postCommand(const QString &command,
|
void postCommand(const QString &command,
|
||||||
GdbCommandFlags flags,
|
GdbCommandFlags flags,
|
||||||
GdbCommandCallback callback = 0,
|
GdbCommandCallback callback = 0,
|
||||||
@@ -245,7 +210,11 @@ private:
|
|||||||
GdbCommandCallback callback = 0,
|
GdbCommandCallback callback = 0,
|
||||||
const char *callbackName = 0,
|
const char *callbackName = 0,
|
||||||
const QVariant &cookie = QVariant());
|
const QVariant &cookie = QVariant());
|
||||||
|
void postCommand(const QString &command,
|
||||||
|
AdapterCallback callback,
|
||||||
|
const char *callbackName,
|
||||||
|
const QVariant &cookie = QVariant());
|
||||||
|
void postCommandHelper(const GdbCommand &cmd);
|
||||||
void setTokenBarrier();
|
void setTokenBarrier();
|
||||||
|
|
||||||
void updateLocals();
|
void updateLocals();
|
||||||
@@ -257,25 +226,36 @@ private slots:
|
|||||||
void readUploadStandardOutput();
|
void readUploadStandardOutput();
|
||||||
void readUploadStandardError();
|
void readUploadStandardError();
|
||||||
void readDebugeeOutput(const QByteArray &data);
|
void readDebugeeOutput(const QByteArray &data);
|
||||||
void stubStarted();
|
|
||||||
void stubError(const QString &msg);
|
|
||||||
void uploadProcError(QProcess::ProcessError error);
|
void uploadProcError(QProcess::ProcessError error);
|
||||||
void emitStartFailed();
|
void emitStartFailed();
|
||||||
|
|
||||||
|
void handleAdapterStarted();
|
||||||
|
void handleAdapterStartFailed(const QString &msg);
|
||||||
|
|
||||||
|
void handleInferiorPrepared();
|
||||||
|
void handleInferiorPreparationFailed(const QString &msg);
|
||||||
|
void handleInferiorStarted();
|
||||||
|
void handleInferiorStartFailed(const QString &msg);
|
||||||
|
void handleInferiorShutDown();
|
||||||
|
void handleInferiorShutdownFailed(const QString &msg);
|
||||||
|
|
||||||
|
void handleAdapterShutDown();
|
||||||
|
void handleAdapterShutdownFailed(const QString &msg);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
int terminationIndex(const QByteArray &buffer, int &length);
|
int terminationIndex(const QByteArray &buffer, int &length);
|
||||||
void handleResponse(const QByteArray &buff);
|
void handleResponse(const QByteArray &buff);
|
||||||
void handleStart(const GdbResultRecord &response, const QVariant &);
|
void handleStart(const GdbResultRecord &response, const QVariant &);
|
||||||
void handleAttach(const GdbResultRecord &, const QVariant &);
|
void handleAttach(const GdbResultRecord &, const QVariant &);
|
||||||
void handleStubAttached(const GdbResultRecord &, const QVariant &);
|
|
||||||
void handleAqcuiredInferior();
|
void handleAqcuiredInferior();
|
||||||
void handleAsyncOutput2(const GdbResultRecord &, const QVariant &cookie);
|
|
||||||
void handleAsyncOutput2(const GdbMi &data);
|
|
||||||
void handleAsyncOutput(const GdbMi &data);
|
void handleAsyncOutput(const GdbMi &data);
|
||||||
|
void handleStop1(const GdbResultRecord &, const QVariant &cookie);
|
||||||
|
void handleStop2(const GdbResultRecord &, const QVariant &cookie);
|
||||||
|
void handleStop2(const GdbMi &data);
|
||||||
void handleResultRecord(const GdbResultRecord &response);
|
void handleResultRecord(const GdbResultRecord &response);
|
||||||
void handleFileExecAndSymbols(const GdbResultRecord &response, const QVariant &);
|
void handleFileExecAndSymbols(const GdbResultRecord &response, const QVariant &);
|
||||||
void handleExecContinue(const GdbResultRecord &response, const QVariant &);
|
void handleExecContinue(const GdbResultRecord &response, const QVariant &);
|
||||||
void handleExecRun(const GdbResultRecord &response, const QVariant &);
|
//void handleExecRun(const GdbResultRecord &response, const QVariant &);
|
||||||
void handleExecJumpToLine(const GdbResultRecord &response, const QVariant &);
|
void handleExecJumpToLine(const GdbResultRecord &response, const QVariant &);
|
||||||
void handleExecRunToFunction(const GdbResultRecord &response, const QVariant &);
|
void handleExecRunToFunction(const GdbResultRecord &response, const QVariant &);
|
||||||
void handleInfoShared(const GdbResultRecord &response, const QVariant &);
|
void handleInfoShared(const GdbResultRecord &response, const QVariant &);
|
||||||
@@ -306,7 +286,6 @@ private:
|
|||||||
QList<WatchData> *insertions);
|
QList<WatchData> *insertions);
|
||||||
const bool m_dumperInjectionLoad;
|
const bool m_dumperInjectionLoad;
|
||||||
|
|
||||||
OutputCollector m_outputCollector;
|
|
||||||
QTextCodec *m_outputCodec;
|
QTextCodec *m_outputCodec;
|
||||||
QTextCodec::ConverterState m_outputCodecState;
|
QTextCodec::ConverterState m_outputCodecState;
|
||||||
|
|
||||||
@@ -315,8 +294,6 @@ private:
|
|||||||
AbstractGdbAdapter *m_gdbAdapter;
|
AbstractGdbAdapter *m_gdbAdapter;
|
||||||
QProcess m_uploadProc;
|
QProcess m_uploadProc;
|
||||||
|
|
||||||
Core::Utils::ConsoleProcess m_stubProc;
|
|
||||||
|
|
||||||
QHash<int, GdbCommand> m_cookieForToken;
|
QHash<int, GdbCommand> m_cookieForToken;
|
||||||
QHash<int, QByteArray> m_customOutputForToken;
|
QHash<int, QByteArray> m_customOutputForToken;
|
||||||
|
|
||||||
@@ -448,7 +425,11 @@ private:
|
|||||||
QString m_currentFrame;
|
QString m_currentFrame;
|
||||||
QMap<QString, QString> m_varToType;
|
QMap<QString, QString> m_varToType;
|
||||||
|
|
||||||
bool m_autoContinue;
|
typedef void (GdbEngine::*Continuation)();
|
||||||
|
// function called after all previous responses have been received
|
||||||
|
Continuation m_continuationAfterDone;
|
||||||
|
void handleInitialBreakpointsSet();
|
||||||
|
|
||||||
bool m_waitingForFirstBreakpointToBeHit;
|
bool m_waitingForFirstBreakpointToBeHit;
|
||||||
bool m_modulesListOutdated;
|
bool m_modulesListOutdated;
|
||||||
|
|
||||||
@@ -458,6 +439,8 @@ private:
|
|||||||
IDebuggerManagerAccessForEngines * const qq;
|
IDebuggerManagerAccessForEngines * const qq;
|
||||||
DebuggerStartParametersPtr m_startParameters;
|
DebuggerStartParametersPtr m_startParameters;
|
||||||
// make sure to re-initialize new members in initializeVariables();
|
// make sure to re-initialize new members in initializeVariables();
|
||||||
|
public:
|
||||||
|
OutputCollector m_outputCollector;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace Internal
|
} // namespace Internal
|
||||||
|
|||||||
291
src/plugins/debugger/gdb/plaingdbadapter.cpp
Normal file
291
src/plugins/debugger/gdb/plaingdbadapter.cpp
Normal file
@@ -0,0 +1,291 @@
|
|||||||
|
/**************************************************************************
|
||||||
|
**
|
||||||
|
** This file is part of Qt Creator
|
||||||
|
**
|
||||||
|
** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
|
||||||
|
**
|
||||||
|
** Contact: Nokia Corporation (qt-info@nokia.com)
|
||||||
|
**
|
||||||
|
** Commercial Usage
|
||||||
|
**
|
||||||
|
** Licensees holding valid Qt Commercial licenses may use this file in
|
||||||
|
** accordance with the Qt Commercial License Agreement provided with the
|
||||||
|
** Software or, alternatively, in accordance with the terms contained in
|
||||||
|
** a written agreement between you and Nokia.
|
||||||
|
**
|
||||||
|
** GNU Lesser General Public License Usage
|
||||||
|
**
|
||||||
|
** Alternatively, this file may be used under the terms of the GNU Lesser
|
||||||
|
** General Public License version 2.1 as published by the Free Software
|
||||||
|
** Foundation and appearing in the file LICENSE.LGPL included in the
|
||||||
|
** packaging of this file. Please review the following information to
|
||||||
|
** ensure the GNU Lesser General Public License version 2.1 requirements
|
||||||
|
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
|
||||||
|
**
|
||||||
|
** If you are unsure which license is appropriate for your use, please
|
||||||
|
** contact the sales department at http://qt.nokia.com/contact.
|
||||||
|
**
|
||||||
|
**************************************************************************/
|
||||||
|
|
||||||
|
#include "plaingdbadapter.h"
|
||||||
|
|
||||||
|
#include "debuggeractions.h"
|
||||||
|
#include "gdbengine.h"
|
||||||
|
#include "procinterrupt.h"
|
||||||
|
|
||||||
|
#include <utils/qtcassert.h>
|
||||||
|
#include <coreplugin/icore.h>
|
||||||
|
|
||||||
|
#include <QtCore/QFileInfo>
|
||||||
|
#include <QtGui/QMessageBox>
|
||||||
|
|
||||||
|
namespace Debugger {
|
||||||
|
namespace Internal {
|
||||||
|
|
||||||
|
#define STRINGIFY_INTERNAL(x) #x
|
||||||
|
#define STRINGIFY(x) STRINGIFY_INTERNAL(x)
|
||||||
|
#define CB(callback) \
|
||||||
|
static_cast<GdbEngine::AdapterCallback>(&PlainGdbAdapter::callback), \
|
||||||
|
STRINGIFY(callback)
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////
|
||||||
|
//
|
||||||
|
// PlainGdbAdapter
|
||||||
|
//
|
||||||
|
///////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
PlainGdbAdapter::PlainGdbAdapter(GdbEngine *engine, QObject *parent)
|
||||||
|
: AbstractGdbAdapter(engine, parent)
|
||||||
|
{
|
||||||
|
connect(&m_gdbProc, SIGNAL(error(QProcess::ProcessError)),
|
||||||
|
this, SIGNAL(error(QProcess::ProcessError)));
|
||||||
|
connect(&m_gdbProc, SIGNAL(readyReadStandardOutput()),
|
||||||
|
this, SIGNAL(readyReadStandardOutput()));
|
||||||
|
connect(&m_gdbProc, SIGNAL(readyReadStandardError()),
|
||||||
|
this, SIGNAL(readyReadStandardError()));
|
||||||
|
connect(&m_gdbProc, SIGNAL(started()),
|
||||||
|
this, SIGNAL(adapterStarted()));
|
||||||
|
connect(&m_gdbProc, SIGNAL(finished(int, QProcess::ExitStatus)),
|
||||||
|
this, SLOT(handleFinished(int, QProcess::ExitStatus)));
|
||||||
|
|
||||||
|
m_stubProc.setMode(Core::Utils::ConsoleProcess::Debug);
|
||||||
|
#ifdef Q_OS_UNIX
|
||||||
|
m_stubProc.setSettings(Core::ICore::instance()->settings());
|
||||||
|
#endif
|
||||||
|
|
||||||
|
connect(&m_stubProc, SIGNAL(processError(QString)),
|
||||||
|
this, SLOT(stubError(QString)));
|
||||||
|
connect(&m_stubProc, SIGNAL(processStarted()),
|
||||||
|
this, SLOT(stubStarted()));
|
||||||
|
// FIXME:
|
||||||
|
// connect(&m_stubProc, SIGNAL(wrapperStopped()),
|
||||||
|
// m_manager, SLOT(exitDebugger()));
|
||||||
|
}
|
||||||
|
|
||||||
|
void PlainGdbAdapter::startAdapter(const DebuggerStartParametersPtr &sp)
|
||||||
|
{
|
||||||
|
debugMessage(_("TRYING TO START ADAPTER"));
|
||||||
|
m_startParameters = sp;
|
||||||
|
|
||||||
|
QStringList gdbArgs;
|
||||||
|
gdbArgs.prepend(_("mi"));
|
||||||
|
gdbArgs.prepend(_("-i"));
|
||||||
|
|
||||||
|
if (m_startParameters->useTerminal) {
|
||||||
|
m_stubProc.stop(); // We leave the console open, so recycle it now.
|
||||||
|
|
||||||
|
m_stubProc.setWorkingDirectory(m_startParameters->workingDir);
|
||||||
|
m_stubProc.setEnvironment(m_startParameters->environment);
|
||||||
|
if (!m_stubProc.start(m_startParameters->executable,
|
||||||
|
m_startParameters->processArgs)) {
|
||||||
|
// Error message for user is delivered via a signal.
|
||||||
|
emitAdapterStartFailed(QString());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (!m_engine->m_outputCollector.listen()) {
|
||||||
|
emitAdapterStartFailed(tr("Cannot set up communication with child process: %1")
|
||||||
|
.arg(m_engine->m_outputCollector.errorString()));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
gdbArgs.prepend(_("--tty=") + m_engine->m_outputCollector.serverName());
|
||||||
|
|
||||||
|
if (!m_startParameters->workingDir.isEmpty())
|
||||||
|
setWorkingDirectory(m_startParameters->workingDir);
|
||||||
|
if (!m_startParameters->environment.isEmpty())
|
||||||
|
setEnvironment(m_startParameters->environment);
|
||||||
|
}
|
||||||
|
|
||||||
|
QString location = theDebuggerStringSetting(GdbLocation);
|
||||||
|
//showStatusMessage(tr("Starting Debugger: ") + loc + _c(' ') + gdbArgs.join(_(" ")));
|
||||||
|
m_gdbProc.start(location, gdbArgs);
|
||||||
|
}
|
||||||
|
|
||||||
|
void PlainGdbAdapter::prepareInferior()
|
||||||
|
{
|
||||||
|
if (!m_startParameters->processArgs.isEmpty())
|
||||||
|
m_engine->postCommand(_("-exec-arguments ") + m_startParameters->processArgs.join(_(" ")));
|
||||||
|
QFileInfo fi(m_engine->startParameters().executable);
|
||||||
|
m_engine->postCommand(_("-file-exec-and-symbols \"%1\"").arg(fi.absoluteFilePath()),
|
||||||
|
CB(handleFileExecAndSymbols));
|
||||||
|
}
|
||||||
|
|
||||||
|
void PlainGdbAdapter::handleFileExecAndSymbols(const GdbResultRecord &response, const QVariant &)
|
||||||
|
{
|
||||||
|
if (response.resultClass == GdbResultDone) {
|
||||||
|
//m_breakHandler->clearBreakMarkers();
|
||||||
|
emit inferiorPrepared();
|
||||||
|
} else if (response.resultClass == GdbResultError) {
|
||||||
|
QString msg = tr("Starting executable failed:\n") +
|
||||||
|
__(response.data.findChild("msg").data());
|
||||||
|
emit inferiorPreparationFailed(msg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void PlainGdbAdapter::startInferior()
|
||||||
|
{
|
||||||
|
m_engine->postCommand(_("-exec-run"), CB(handleExecRun));
|
||||||
|
/*
|
||||||
|
#ifdef Q_OS_MAC
|
||||||
|
m_engine->postCommand(_("sharedlibrary apply-load-rules all"));
|
||||||
|
// On MacOS, breaking in at the entry point wreaks havoc.
|
||||||
|
m_engine->postCommand(_("tbreak main"));
|
||||||
|
m_waitingForFirstBreakpointToBeHit = true;
|
||||||
|
m_engine->postCommand(_("-exec-run"), CB(handleExecRun));
|
||||||
|
#else
|
||||||
|
// FIXME:
|
||||||
|
// if (!m_dumperInjectionLoad)
|
||||||
|
// m_engine->postCommand(_("set auto-solib-add off"));
|
||||||
|
m_engine->postCommand(_("info target"), CB(handleInfoTarget));
|
||||||
|
#endif
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
|
||||||
|
void PlainGdbAdapter::handleInfoTarget(const GdbResultRecord &response, const QVariant &)
|
||||||
|
{
|
||||||
|
#if defined(Q_OS_MAC)
|
||||||
|
Q_UNUSED(response)
|
||||||
|
#else
|
||||||
|
if (response.resultClass == GdbResultDone) {
|
||||||
|
// [some leading stdout here]
|
||||||
|
// >&" Entry point: 0x80831f0 0x08048134 - 0x08048147 is .interp\n"
|
||||||
|
// [some trailing stdout here]
|
||||||
|
QString msg = _(response.data.findChild("consolestreamoutput").data());
|
||||||
|
QRegExp needle(_("\\bEntry point: (0x[0-9a-f]+)\\b"));
|
||||||
|
if (needle.indexIn(msg) != -1) {
|
||||||
|
//debugMessage(_("STREAM: ") + msg + " " + needle.cap(1));
|
||||||
|
m_engine->postCommand(_("tbreak *") + needle.cap(1));
|
||||||
|
// FIXME: m_waitingForFirstBreakpointToBeHit = true;
|
||||||
|
m_engine->postCommand(_("-exec-run"), CB(handleExecRun));
|
||||||
|
} else {
|
||||||
|
debugMessage(_("PARSING START ADDRESS FAILED: ") + msg);
|
||||||
|
emit inferiorStartFailed(_("Parsing start address failed"));
|
||||||
|
}
|
||||||
|
} else if (response.resultClass == GdbResultError) {
|
||||||
|
debugMessage(_("FETCHING START ADDRESS FAILED: " + response.toString()));
|
||||||
|
emit inferiorStartFailed(_("Fetching start address failed"));
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void PlainGdbAdapter::handleExecRun(const GdbResultRecord &response, const QVariant &)
|
||||||
|
{
|
||||||
|
if (response.resultClass == GdbResultRunning) {
|
||||||
|
emit inferiorStarted();
|
||||||
|
} else {
|
||||||
|
QTC_ASSERT(response.resultClass == GdbResultError, /**/);
|
||||||
|
const QByteArray &msg = response.data.findChild("msg").data();
|
||||||
|
//QTC_ASSERT(status() == DebuggerInferiorRunning, /**/);
|
||||||
|
//interruptInferior();
|
||||||
|
emit inferiorStartFailed(msg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void PlainGdbAdapter::interruptInferior()
|
||||||
|
{
|
||||||
|
debugMessage(_("TRYING TO INTERUPT INFERIOR"));
|
||||||
|
if (m_engine->startMode() == StartRemote) {
|
||||||
|
m_engine->postCommand(_("-exec-interrupt"));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const qint64 attachedPID = m_engine->inferiorPid();
|
||||||
|
if (attachedPID <= 0) {
|
||||||
|
debugMessage(_("TRYING TO INTERRUPT INFERIOR BEFORE PID WAS OBTAINED"));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!interruptProcess(attachedPID))
|
||||||
|
debugMessage(_("CANNOT INTERRUPT %1").arg(attachedPID));
|
||||||
|
}
|
||||||
|
|
||||||
|
void PlainGdbAdapter::shutdownAdapter()
|
||||||
|
{
|
||||||
|
m_engine->postCommand(_("-gdb-exit"), CB(handleExit));
|
||||||
|
// 20s can easily happen when loading webkit debug information
|
||||||
|
if (!m_gdbProc.waitForFinished(20000)) {
|
||||||
|
debugMessage(_("FORCING TERMINATION: %1")
|
||||||
|
.arg(state()));
|
||||||
|
m_gdbProc.terminate();
|
||||||
|
m_gdbProc.waitForFinished(20000);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (state() != QProcess::NotRunning) {
|
||||||
|
debugMessage(_("PROBLEM STOPPING DEBUGGER: STATE %1")
|
||||||
|
.arg(state()));
|
||||||
|
m_gdbProc.kill();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void PlainGdbAdapter::handleExit(const GdbResultRecord &response, const QVariant &)
|
||||||
|
{
|
||||||
|
if (response.resultClass == GdbResultDone) {
|
||||||
|
emit adapterShutDown();
|
||||||
|
} else if (response.resultClass == GdbResultError) {
|
||||||
|
QString msg = tr("Gdb process could not be stopped:\n") +
|
||||||
|
__(response.data.findChild("msg").data());
|
||||||
|
emit adapterShutdownFailed(msg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void PlainGdbAdapter::handleFinished(int, QProcess::ExitStatus)
|
||||||
|
{
|
||||||
|
debugMessage(_("GDB PROESS FINISHED"));
|
||||||
|
}
|
||||||
|
|
||||||
|
void PlainGdbAdapter::shutdownInferior()
|
||||||
|
{
|
||||||
|
m_engine->postCommand(_("kill"));
|
||||||
|
}
|
||||||
|
|
||||||
|
void PlainGdbAdapter::stubStarted()
|
||||||
|
{
|
||||||
|
const qint64 attachedPID = m_stubProc.applicationPID();
|
||||||
|
emit inferiorPidChanged(attachedPID);
|
||||||
|
m_engine->postCommand(_("attach %1").arg(attachedPID), CB(handleStubAttached));
|
||||||
|
}
|
||||||
|
|
||||||
|
void PlainGdbAdapter::handleStubAttached(const GdbResultRecord &, const QVariant &)
|
||||||
|
{
|
||||||
|
qDebug() << "STUB ATTACHED, FIXME";
|
||||||
|
//qq->notifyInferiorStopped();
|
||||||
|
//handleAqcuiredInferior();
|
||||||
|
// FIXME: m_autoContinue = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void PlainGdbAdapter::stubError(const QString &msg)
|
||||||
|
{
|
||||||
|
QMessageBox::critical(m_engine->mainWindow(), tr("Debugger Error"), msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
void PlainGdbAdapter::emitAdapterStartFailed(const QString &msg)
|
||||||
|
{
|
||||||
|
// QMessageBox::critical(mainWindow(), tr("Debugger Startup Failure"),
|
||||||
|
// tr("Cannot start debugger: %1").arg(m_gdbAdapter->errorString()));
|
||||||
|
m_stubProc.blockSignals(true);
|
||||||
|
m_stubProc.stop();
|
||||||
|
m_stubProc.blockSignals(false);
|
||||||
|
emit adapterStartFailed(msg);
|
||||||
|
}
|
||||||
|
} // namespace Internal
|
||||||
|
} // namespace Debugger
|
||||||
98
src/plugins/debugger/gdb/plaingdbadapter.h
Normal file
98
src/plugins/debugger/gdb/plaingdbadapter.h
Normal file
@@ -0,0 +1,98 @@
|
|||||||
|
/**************************************************************************
|
||||||
|
**
|
||||||
|
** This file is part of Qt Creator
|
||||||
|
**
|
||||||
|
** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
|
||||||
|
**
|
||||||
|
** Contact: Nokia Corporation (qt-info@nokia.com)
|
||||||
|
**
|
||||||
|
** Commercial Usage
|
||||||
|
**
|
||||||
|
** Licensees holding valid Qt Commercial licenses may use this file in
|
||||||
|
** accordance with the Qt Commercial License Agreement provided with the
|
||||||
|
** Software or, alternatively, in accordance with the terms contained in
|
||||||
|
** a written agreement between you and Nokia.
|
||||||
|
**
|
||||||
|
** GNU Lesser General Public License Usage
|
||||||
|
**
|
||||||
|
** Alternatively, this file may be used under the terms of the GNU Lesser
|
||||||
|
** General Public License version 2.1 as published by the Free Software
|
||||||
|
** Foundation and appearing in the file LICENSE.LGPL included in the
|
||||||
|
** packaging of this file. Please review the following information to
|
||||||
|
** ensure the GNU Lesser General Public License version 2.1 requirements
|
||||||
|
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
|
||||||
|
**
|
||||||
|
** If you are unsure which license is appropriate for your use, please
|
||||||
|
** contact the sales department at http://qt.nokia.com/contact.
|
||||||
|
**
|
||||||
|
**************************************************************************/
|
||||||
|
|
||||||
|
#ifndef DEBUGGER_PLAINGDBADAPTER_H
|
||||||
|
#define DEBUGGER_PLAINGDBADAPTER_H
|
||||||
|
|
||||||
|
#include "abstractgdbadapter.h"
|
||||||
|
#include "gdbengine.h"
|
||||||
|
#include "outputcollector.h"
|
||||||
|
|
||||||
|
#include <consoleprocess.h>
|
||||||
|
|
||||||
|
#include <QtCore/QDebug>
|
||||||
|
#include <QtCore/QProcess>
|
||||||
|
|
||||||
|
namespace Debugger {
|
||||||
|
namespace Internal {
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////
|
||||||
|
//
|
||||||
|
// PlainGdbAdapter
|
||||||
|
//
|
||||||
|
///////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
class PlainGdbAdapter : public AbstractGdbAdapter
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
PlainGdbAdapter(GdbEngine *engine, QObject *parent = 0);
|
||||||
|
|
||||||
|
//void kill() { m_gdbProc.kill(); }
|
||||||
|
//void terminate() { m_gdbProc.terminate(); }
|
||||||
|
QProcess::ProcessState state() const { return m_gdbProc.state(); }
|
||||||
|
QString errorString() const { return m_gdbProc.errorString(); }
|
||||||
|
QByteArray readAllStandardError() { return m_gdbProc.readAllStandardError(); }
|
||||||
|
QByteArray readAllStandardOutput() { return m_gdbProc.readAllStandardOutput(); }
|
||||||
|
qint64 write(const char *data) { return m_gdbProc.write(data); }
|
||||||
|
void setWorkingDirectory(const QString &dir) { m_gdbProc.setWorkingDirectory(dir); }
|
||||||
|
void setEnvironment(const QStringList &env) { m_gdbProc.setEnvironment(env); }
|
||||||
|
bool isAdapter() const { return false; }
|
||||||
|
void interruptInferior();
|
||||||
|
|
||||||
|
void startAdapter(const DebuggerStartParametersPtr &sp);
|
||||||
|
void prepareInferior();
|
||||||
|
void startInferior();
|
||||||
|
void shutdownInferior();
|
||||||
|
void shutdownAdapter();
|
||||||
|
|
||||||
|
private:
|
||||||
|
void handleFileExecAndSymbols(const GdbResultRecord &, const QVariant &);
|
||||||
|
void handleExit(const GdbResultRecord &, const QVariant &);
|
||||||
|
void handleStubAttached(const GdbResultRecord &, const QVariant &);
|
||||||
|
void handleExecRun(const GdbResultRecord &response, const QVariant &);
|
||||||
|
void handleInfoTarget(const GdbResultRecord &response, const QVariant &);
|
||||||
|
|
||||||
|
void debugMessage(const QString &msg) { m_engine->debugMessage(msg); }
|
||||||
|
void emitAdapterStartFailed(const QString &msg);
|
||||||
|
Q_SLOT void handleFinished(int, QProcess::ExitStatus);
|
||||||
|
Q_SLOT void stubStarted();
|
||||||
|
Q_SLOT void stubError(const QString &msg);
|
||||||
|
|
||||||
|
QProcess m_gdbProc;
|
||||||
|
DebuggerStartParametersPtr m_startParameters;
|
||||||
|
Core::Utils::ConsoleProcess m_stubProc;
|
||||||
|
OutputCollector m_outputCollector;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace Internal
|
||||||
|
} // namespace Debugger
|
||||||
|
|
||||||
|
#endif // DEBUGGER_PLAINGDBADAPTER_H
|
||||||
@@ -75,7 +75,8 @@ static QByteArray dumpRegister(int n, uint value)
|
|||||||
namespace Debugger {
|
namespace Debugger {
|
||||||
namespace Internal {
|
namespace Internal {
|
||||||
|
|
||||||
TrkGdbAdapter::TrkGdbAdapter(const TrkOptionsPtr &options) :
|
TrkGdbAdapter::TrkGdbAdapter(GdbEngine *engine, const TrkOptionsPtr &options) :
|
||||||
|
AbstractGdbAdapter(engine),
|
||||||
m_options(options),
|
m_options(options),
|
||||||
m_running(false),
|
m_running(false),
|
||||||
m_gdbAckMode(true),
|
m_gdbAckMode(true),
|
||||||
@@ -216,19 +217,22 @@ QByteArray TrkGdbAdapter::trkStepRangeMessage(byte option)
|
|||||||
return ba;
|
return ba;
|
||||||
}
|
}
|
||||||
|
|
||||||
void TrkGdbAdapter::startInferior()
|
void TrkGdbAdapter::startInferiorEarly()
|
||||||
{
|
{
|
||||||
QString errorMessage;
|
QString errorMessage;
|
||||||
const QString device = effectiveTrkDevice();
|
const QString device = effectiveTrkDevice();
|
||||||
if (!m_trkDevice.open(device, &errorMessage)) {
|
if (!m_trkDevice.open(device, &errorMessage)) {
|
||||||
emit output(QString::fromLatin1("Waiting on %1 (%2)").arg(device, errorMessage));
|
logMessage(QString::fromLatin1("Waiting on %1 (%2)").arg(device, errorMessage));
|
||||||
// Do not loop forever
|
// Do not loop forever
|
||||||
if (m_waitCount++ < (m_options->mode == TrkOptions::BlueTooth ? 60 : 5)) {
|
if (m_waitCount++ < (m_options->mode == TrkOptions::BlueTooth ? 60 : 5)) {
|
||||||
QTimer::singleShot(1000, this, SLOT(startInferior()));
|
QTimer::singleShot(1000, this, SLOT(startInferiorEarly()));
|
||||||
} else {
|
} else {
|
||||||
emit output(QString::fromLatin1("Failed to connect to %1 after %2 attempts").arg(device).arg(m_waitCount));
|
QString msg = QString::fromLatin1("Failed to connect to %1 after "
|
||||||
emit finished(-44, QProcess::CrashExit);
|
"%2 attempts").arg(device).arg(m_waitCount);
|
||||||
|
logMessage(msg);
|
||||||
|
emit adapterStartFailed(msg);
|
||||||
}
|
}
|
||||||
|
QTimer::singleShot(1000, this, SLOT(startInferiorEarly()));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1292,38 +1296,43 @@ void TrkGdbAdapter::interruptInferior()
|
|||||||
|
|
||||||
void TrkGdbAdapter::handleGdbError(QProcess::ProcessError error)
|
void TrkGdbAdapter::handleGdbError(QProcess::ProcessError error)
|
||||||
{
|
{
|
||||||
emit output(QString("GDB: Process Error %1: %2").arg(error).arg(errorString()));
|
logMessage(QString("GDB: Process Error %1: %2").arg(error).arg(errorString()));
|
||||||
}
|
}
|
||||||
|
|
||||||
void TrkGdbAdapter::handleGdbFinished(int exitCode, QProcess::ExitStatus exitStatus)
|
void TrkGdbAdapter::handleGdbFinished(int exitCode, QProcess::ExitStatus exitStatus)
|
||||||
{
|
{
|
||||||
emit output(QString("GDB: ProcessFinished %1 %2").arg(exitCode).arg(exitStatus));
|
logMessage(QString("GDB: ProcessFinished %1 %2").arg(exitCode).arg(exitStatus));
|
||||||
}
|
}
|
||||||
|
|
||||||
void TrkGdbAdapter::handleGdbStarted()
|
void TrkGdbAdapter::handleGdbStarted()
|
||||||
{
|
{
|
||||||
emit output(QString("GDB: Process Started"));
|
logMessage(QString("GDB: Process Started"));
|
||||||
emit started();
|
emit adapterStarted();
|
||||||
}
|
}
|
||||||
|
|
||||||
void TrkGdbAdapter::handleGdbStateChanged(QProcess::ProcessState newState)
|
void TrkGdbAdapter::handleGdbStateChanged(QProcess::ProcessState newState)
|
||||||
{
|
{
|
||||||
emit output(QString("GDB: Process State %1").arg(newState));
|
logMessage(QString("GDB: Process State %1").arg(newState));
|
||||||
}
|
}
|
||||||
|
|
||||||
void TrkGdbAdapter::run()
|
void TrkGdbAdapter::startAdapter(const DebuggerStartParametersPtr &sp)
|
||||||
{
|
{
|
||||||
emit output(QLatin1String("### Starting TrkGdbAdapter"));
|
m_startParameters = sp;
|
||||||
|
logMessage(QLatin1String("### Starting TrkGdbAdapter"));
|
||||||
if (m_options->mode == TrkOptions::BlueTooth) {
|
if (m_options->mode == TrkOptions::BlueTooth) {
|
||||||
const QString device = effectiveTrkDevice();
|
const QString device = effectiveTrkDevice();
|
||||||
const QString blueToothListener = QLatin1String("rfcomm");
|
const QString blueToothListener = QLatin1String("rfcomm");
|
||||||
emit output(QString::fromLatin1("### Starting BlueTooth listener %1 on %2").arg(blueToothListener, device));
|
logMessage(QString::fromLatin1("### Starting BlueTooth listener %1 on %2")
|
||||||
m_rfcommProc.start(blueToothListener + QLatin1String(" -r listen ") + m_options->blueToothDevice + QLatin1String(" 1"));
|
.arg(blueToothListener, device));
|
||||||
|
m_rfcommProc.start(blueToothListener + QLatin1String(" -r listen ")
|
||||||
|
+ m_options->blueToothDevice + QLatin1String(" 1"));
|
||||||
m_rfcommProc.waitForStarted();
|
m_rfcommProc.waitForStarted();
|
||||||
if (m_rfcommProc.state() != QProcess::Running) {
|
if (m_rfcommProc.state() != QProcess::Running) {
|
||||||
const QString msg = QString::fromLocal8Bit(m_rfcommProc.readAllStandardError());
|
QString msg = QString::fromLatin1("Failed to start BlueTooth "
|
||||||
emit output(QString::fromLatin1("Failed to start BlueTooth listener %1 on %2: %3\n%4").arg(blueToothListener, device, m_rfcommProc.errorString(), msg));
|
"listener %1 on %2: %3\n");
|
||||||
emit finished(-44, QProcess::CrashExit);
|
msg = msg.arg(blueToothListener, device, m_rfcommProc.errorString());
|
||||||
|
msg += QString::fromLocal8Bit(m_rfcommProc.readAllStandardError());
|
||||||
|
emit adapterStartFailed(msg);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1334,7 +1343,19 @@ void TrkGdbAdapter::run()
|
|||||||
connect(&m_trkDevice, SIGNAL(error(QString)),
|
connect(&m_trkDevice, SIGNAL(error(QString)),
|
||||||
this, SLOT(handleTrkError(QString)));
|
this, SLOT(handleTrkError(QString)));
|
||||||
|
|
||||||
startInferior();
|
startInferiorEarly();
|
||||||
|
}
|
||||||
|
|
||||||
|
void TrkGdbAdapter::prepareInferior()
|
||||||
|
{
|
||||||
|
// we already prepared the inferior during the adapter start
|
||||||
|
emit inferiorPrepared();
|
||||||
|
}
|
||||||
|
|
||||||
|
void TrkGdbAdapter::startInferior()
|
||||||
|
{
|
||||||
|
// we already started the inferior during the adapter start
|
||||||
|
emit inferiorStarted();
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef Q_OS_WIN
|
#ifdef Q_OS_WIN
|
||||||
@@ -1363,9 +1384,10 @@ static void setGdbCygwinEnvironment(const QString &cygwin, QProcess *process)
|
|||||||
void TrkGdbAdapter::startGdb()
|
void TrkGdbAdapter::startGdb()
|
||||||
{
|
{
|
||||||
if (!m_gdbServer.listen(QHostAddress(gdbServerIP()), gdbServerPort())) {
|
if (!m_gdbServer.listen(QHostAddress(gdbServerIP()), gdbServerPort())) {
|
||||||
logMessage(QString("Unable to start the gdb server at %1: %2.")
|
QString msg = QString("Unable to start the gdb server at %1: %2.")
|
||||||
.arg(m_gdbServerName).arg(m_gdbServer.errorString()));
|
.arg(m_gdbServerName).arg(m_gdbServer.errorString());
|
||||||
emit finished(-45, QProcess::CrashExit);
|
logMessage(msg);
|
||||||
|
emit adapterStartFailed(msg);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1376,7 +1398,7 @@ void TrkGdbAdapter::startGdb()
|
|||||||
this, SLOT(handleGdbConnection()));
|
this, SLOT(handleGdbConnection()));
|
||||||
|
|
||||||
logMessage("STARTING GDB");
|
logMessage("STARTING GDB");
|
||||||
emit output(QString::fromLatin1("### Starting gdb %1").arg(m_options->gdb));
|
logMessage(QString::fromLatin1("### Starting gdb %1").arg(m_options->gdb));
|
||||||
QStringList gdbArgs;
|
QStringList gdbArgs;
|
||||||
gdbArgs.append(QLatin1String("--nx")); // Do not read .gdbinit file
|
gdbArgs.append(QLatin1String("--nx")); // Do not read .gdbinit file
|
||||||
gdbArgs.append(QLatin1String("-i"));
|
gdbArgs.append(QLatin1String("-i"));
|
||||||
@@ -1405,52 +1427,44 @@ void TrkGdbAdapter::sendGdbMessage(const QString &msg, GdbCallback callback,
|
|||||||
void TrkGdbAdapter::handleRfcommReadyReadStandardError()
|
void TrkGdbAdapter::handleRfcommReadyReadStandardError()
|
||||||
{
|
{
|
||||||
QByteArray ba = m_rfcommProc.readAllStandardError();
|
QByteArray ba = m_rfcommProc.readAllStandardError();
|
||||||
emit output(QString("RFCONN stderr: %1").arg(QString::fromLatin1(ba)));
|
logMessage(QString("RFCONN stderr: %1").arg(QString::fromLatin1(ba)));
|
||||||
}
|
}
|
||||||
|
|
||||||
void TrkGdbAdapter::handleRfcommReadyReadStandardOutput()
|
void TrkGdbAdapter::handleRfcommReadyReadStandardOutput()
|
||||||
{
|
{
|
||||||
QByteArray ba = m_rfcommProc.readAllStandardOutput();
|
QByteArray ba = m_rfcommProc.readAllStandardOutput();
|
||||||
emit output(QString("RFCONN stdout: %1").arg(QString::fromLatin1(ba)));
|
logMessage(QString("RFCONN stdout: %1").arg(QString::fromLatin1(ba)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void TrkGdbAdapter::handleRfcommError(QProcess::ProcessError error)
|
void TrkGdbAdapter::handleRfcommError(QProcess::ProcessError error)
|
||||||
{
|
{
|
||||||
emit output(QString("RFCOMM: Process Error %1: %2").arg(error).arg(errorString()));
|
logMessage(QString("RFCOMM: Process Error %1: %2").arg(error).arg(errorString()));
|
||||||
}
|
}
|
||||||
|
|
||||||
void TrkGdbAdapter::handleRfcommFinished(int exitCode, QProcess::ExitStatus exitStatus)
|
void TrkGdbAdapter::handleRfcommFinished(int exitCode, QProcess::ExitStatus exitStatus)
|
||||||
{
|
{
|
||||||
emit output(QString("RFCOMM: ProcessFinished %1 %2").arg(exitCode).arg(exitStatus));
|
logMessage(QString("RFCOMM: ProcessFinished %1 %2").arg(exitCode).arg(exitStatus));
|
||||||
}
|
}
|
||||||
|
|
||||||
void TrkGdbAdapter::handleRfcommStarted()
|
void TrkGdbAdapter::handleRfcommStarted()
|
||||||
{
|
{
|
||||||
emit output(QString("RFCOMM: Process Started"));
|
logMessage(QString("RFCOMM: Process Started"));
|
||||||
}
|
}
|
||||||
|
|
||||||
void TrkGdbAdapter::handleRfcommStateChanged(QProcess::ProcessState newState)
|
void TrkGdbAdapter::handleRfcommStateChanged(QProcess::ProcessState newState)
|
||||||
{
|
{
|
||||||
emit output(QString("RFCOMM: Process State %1").arg(newState));
|
logMessage(QString("RFCOMM: Process State %1").arg(newState));
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// GdbProcessBase
|
// GdbProcessBase
|
||||||
//
|
//
|
||||||
|
|
||||||
void TrkGdbAdapter::start(const QString &program, const QStringList &args,
|
|
||||||
QIODevice::OpenMode mode)
|
|
||||||
{
|
|
||||||
Q_UNUSED(mode);
|
|
||||||
Q_UNUSED(program);
|
|
||||||
Q_UNUSED(args);
|
|
||||||
run();
|
|
||||||
}
|
|
||||||
|
|
||||||
void TrkGdbAdapter::kill()
|
void TrkGdbAdapter::kill()
|
||||||
{
|
{
|
||||||
if (m_options->mode == TrkOptions::BlueTooth && m_rfcommProc.state() == QProcess::Running)
|
if (m_options->mode == TrkOptions::BlueTooth
|
||||||
|
&& m_rfcommProc.state() == QProcess::Running)
|
||||||
m_rfcommProc.kill();
|
m_rfcommProc.kill();
|
||||||
m_gdbProc.kill();
|
m_gdbProc.kill();
|
||||||
}
|
}
|
||||||
@@ -1509,6 +1523,17 @@ void TrkGdbAdapter::setEnvironment(const QStringList &env)
|
|||||||
m_gdbProc.setEnvironment(env);
|
m_gdbProc.setEnvironment(env);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void TrkGdbAdapter::shutdownAdapter()
|
||||||
|
{
|
||||||
|
emit adapterShutDown();
|
||||||
|
}
|
||||||
|
|
||||||
|
void TrkGdbAdapter::shutdownInferior()
|
||||||
|
{
|
||||||
|
emit inferiorShutDown();
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
void TrkGdbAdapter::attach()
|
void TrkGdbAdapter::attach()
|
||||||
{
|
{
|
||||||
#ifdef STANDALONE_RUNNER
|
#ifdef STANDALONE_RUNNER
|
||||||
@@ -1522,6 +1547,7 @@ void TrkGdbAdapter::attach()
|
|||||||
m_engine->postCommand(_("target remote ") + gdbServerName());
|
m_engine->postCommand(_("target remote ") + gdbServerName());
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
} // namespace Internal
|
} // namespace Internal
|
||||||
} // namespace Debugger
|
} // namespace Debugger
|
||||||
|
|||||||
@@ -71,7 +71,7 @@ public:
|
|||||||
typedef trk::Callback<const GdbResult &> GdbCallback;
|
typedef trk::Callback<const GdbResult &> GdbCallback;
|
||||||
typedef QSharedPointer<TrkOptions> TrkOptionsPtr;
|
typedef QSharedPointer<TrkOptions> TrkOptionsPtr;
|
||||||
|
|
||||||
explicit TrkGdbAdapter(const TrkOptionsPtr &options);
|
TrkGdbAdapter(GdbEngine *engine, const TrkOptionsPtr &options);
|
||||||
~TrkGdbAdapter();
|
~TrkGdbAdapter();
|
||||||
void setGdbServerName(const QString &name);
|
void setGdbServerName(const QString &name);
|
||||||
QString gdbServerName() const { return m_gdbServerName; }
|
QString gdbServerName() const { return m_gdbServerName; }
|
||||||
@@ -80,22 +80,14 @@ public:
|
|||||||
void setVerbose(int verbose) { m_verbose = verbose; }
|
void setVerbose(int verbose) { m_verbose = verbose; }
|
||||||
void setBufferedMemoryRead(bool b) { m_bufferedMemoryRead = b; }
|
void setBufferedMemoryRead(bool b) { m_bufferedMemoryRead = b; }
|
||||||
trk::Session &session() { return m_session; }
|
trk::Session &session() { return m_session; }
|
||||||
|
void startGdb();
|
||||||
|
|
||||||
// Set a device (from the project) to override the settings.
|
// Set a device (from the project) to override the settings.
|
||||||
QString overrideTrkDevice() const;
|
QString overrideTrkDevice() const;
|
||||||
void setOverrideTrkDevice(const QString &);
|
void setOverrideTrkDevice(const QString &);
|
||||||
|
|
||||||
public slots:
|
|
||||||
void startInferior();
|
|
||||||
void run();
|
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void output(const QString &msg);
|
void output(const QString &msg);
|
||||||
void startSuccessful();
|
|
||||||
void startFailed();
|
|
||||||
|
|
||||||
private slots:
|
|
||||||
void startGdb();
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
friend class RunnerGui;
|
friend class RunnerGui;
|
||||||
@@ -108,6 +100,7 @@ private:
|
|||||||
QProcess m_gdbProc;
|
QProcess m_gdbProc;
|
||||||
QProcess m_rfcommProc;
|
QProcess m_rfcommProc;
|
||||||
bool m_running;
|
bool m_running;
|
||||||
|
DebuggerStartParametersPtr m_startParameters;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
//
|
//
|
||||||
@@ -126,8 +119,15 @@ public:
|
|||||||
void setWorkingDirectory(const QString &dir);
|
void setWorkingDirectory(const QString &dir);
|
||||||
void setEnvironment(const QStringList &env);
|
void setEnvironment(const QStringList &env);
|
||||||
bool isAdapter() const { return true; }
|
bool isAdapter() const { return true; }
|
||||||
void attach();
|
//void attach();
|
||||||
void interruptInferior();
|
void interruptInferior();
|
||||||
|
void startInferiorEarly();
|
||||||
|
|
||||||
|
void startAdapter(const DebuggerStartParametersPtr &sp);
|
||||||
|
void prepareInferior();
|
||||||
|
void startInferior();
|
||||||
|
void shutdownInferior();
|
||||||
|
void shutdownAdapter();
|
||||||
|
|
||||||
//
|
//
|
||||||
// TRK
|
// TRK
|
||||||
|
|||||||
@@ -41,7 +41,7 @@
|
|||||||
|
|
||||||
#include "qmljsastvisitor_p.h"
|
#include "qmljsastvisitor_p.h"
|
||||||
|
|
||||||
QT_BEGIN_NAMESPACE
|
QT_QML_BEGIN_NAMESPACE
|
||||||
|
|
||||||
namespace QmlJS { namespace AST {
|
namespace QmlJS { namespace AST {
|
||||||
|
|
||||||
@@ -55,4 +55,4 @@ Visitor::~Visitor()
|
|||||||
|
|
||||||
} } // namespace QmlJS::AST
|
} } // namespace QmlJS::AST
|
||||||
|
|
||||||
QT_END_NAMESPACE
|
QT_QML_END_NAMESPACE
|
||||||
|
|||||||
Reference in New Issue
Block a user