forked from qt-creator/qt-creator
debugger: rework startup logic
This commit is contained in:
@@ -33,6 +33,8 @@
|
||||
#include <QtCore/QObject>
|
||||
#include <QtCore/QProcess>
|
||||
|
||||
#include "gdbengine.h"
|
||||
|
||||
namespace Debugger {
|
||||
namespace Internal {
|
||||
|
||||
@@ -48,15 +50,10 @@ class AbstractGdbAdapter : public QObject
|
||||
Q_OBJECT
|
||||
|
||||
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 QString errorString() const = 0;
|
||||
virtual QByteArray readAllStandardError() = 0;
|
||||
@@ -66,18 +63,35 @@ public:
|
||||
virtual void setEnvironment(const QStringList &env) = 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;
|
||||
|
||||
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 started();
|
||||
void readyReadStandardOutput();
|
||||
void readyReadStandardError();
|
||||
void finished(int, QProcess::ExitStatus);
|
||||
|
||||
protected:
|
||||
GdbEngine *m_engine;
|
||||
GdbEngine * const m_engine;
|
||||
};
|
||||
|
||||
} // namespace Internal
|
||||
|
||||
@@ -2,6 +2,7 @@ include(../../../shared/trk/trk.pri)
|
||||
|
||||
HEADERS += \
|
||||
$$PWD/abstractgdbadapter.h \
|
||||
$$PWD/plaingdbadapter.h \
|
||||
$$PWD/gdbmi.h \
|
||||
$$PWD/gdbengine.h \
|
||||
$$PWD/gdboptionspage.h \
|
||||
@@ -14,10 +15,11 @@ SOURCES += \
|
||||
$$PWD/gdbmi.cpp \
|
||||
$$PWD/gdbengine.cpp \
|
||||
$$PWD/gdboptionspage.cpp \
|
||||
$$PWD/trkgdbadapter.cpp \
|
||||
$$PWD/plaingdbadapter.cpp \
|
||||
$$PWD/trkoptions.cpp \
|
||||
$$PWD/trkoptionswidget.cpp \
|
||||
$$PWD/trkoptionspage.cpp
|
||||
$$PWD/trkoptionspage.cpp \
|
||||
$$PWD/trkgdbadapter.cpp
|
||||
|
||||
FORMS += $$PWD/gdboptionspage.ui \
|
||||
$$PWD/trkoptionswidget.ui
|
||||
|
||||
@@ -33,6 +33,7 @@
|
||||
#include "gdboptionspage.h"
|
||||
#include "trkoptions.h"
|
||||
#include "trkoptionspage.h"
|
||||
#include "plaingdbadapter.h"
|
||||
#include "trkgdbadapter.h"
|
||||
|
||||
#include "watchutils.h"
|
||||
@@ -82,6 +83,9 @@
|
||||
#endif
|
||||
#include <ctype.h>
|
||||
|
||||
static QString lastFile;
|
||||
static int lastLine;
|
||||
|
||||
namespace Debugger {
|
||||
namespace Internal {
|
||||
using namespace Debugger::Constants;
|
||||
@@ -141,44 +145,13 @@ static QByteArray parsePlainConsoleStream(const GdbResultRecord &record)
|
||||
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(DebuggerManager *parent, AbstractGdbAdapter *gdbAdapter) :
|
||||
GdbEngine::GdbEngine(DebuggerManager *parent) :
|
||||
#ifdef Q_OS_WIN // Do injection loading with MinGW (call loading does not work with 64bit)
|
||||
m_dumperInjectionLoad(true),
|
||||
#else
|
||||
@@ -187,21 +160,24 @@ GdbEngine::GdbEngine(DebuggerManager *parent, AbstractGdbAdapter *gdbAdapter) :
|
||||
m_manager(parent),
|
||||
qq(parent->engineInterface())
|
||||
{
|
||||
m_gdbAdapter = gdbAdapter;
|
||||
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();
|
||||
m_gdbAdapter = 0;
|
||||
}
|
||||
|
||||
GdbEngine::~GdbEngine()
|
||||
{
|
||||
// prevent sending error messages afterwards
|
||||
m_gdbAdapter->disconnect(this);
|
||||
delete m_gdbAdapter;
|
||||
if (m_gdbAdapter) {
|
||||
m_gdbAdapter->disconnect(this);
|
||||
delete m_gdbAdapter;
|
||||
m_gdbAdapter = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void GdbEngine::setGdbAdapter(AbstractGdbAdapter *gdbAdapter)
|
||||
{
|
||||
m_gdbAdapter = gdbAdapter;
|
||||
initializeVariables();
|
||||
initializeConnections();
|
||||
}
|
||||
|
||||
void GdbEngine::initializeConnections()
|
||||
@@ -213,16 +189,31 @@ void GdbEngine::initializeConnections()
|
||||
this, SLOT(readGdbStandardOutput()));
|
||||
connect(m_gdbAdapter, SIGNAL(readyReadStandardError()),
|
||||
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)),
|
||||
this, SLOT(stubError(QString)));
|
||||
connect(&m_stubProc, SIGNAL(processStarted()),
|
||||
this, SLOT(stubStarted()));
|
||||
connect(&m_stubProc, SIGNAL(wrapperStopped()),
|
||||
connect(m_gdbAdapter, SIGNAL(adapterStarted()),
|
||||
this, SLOT(handleAdapterStarted()));
|
||||
connect(m_gdbAdapter, SIGNAL(adapterStartFailed(QString)),
|
||||
this, SLOT(handleAdapterStartFailed(QString)));
|
||||
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()));
|
||||
|
||||
connect(&m_uploadProc, SIGNAL(error(QProcess::ProcessError)),
|
||||
@@ -269,7 +260,7 @@ void GdbEngine::initializeVariables()
|
||||
m_oldestAcceptableToken = -1;
|
||||
m_outputCodec = QTextCodec::codecForLocale();
|
||||
m_pendingRequests = 0;
|
||||
m_autoContinue = false;
|
||||
m_continuationAfterDone = 0;
|
||||
m_waitingForFirstBreakpointToBeHit = false;
|
||||
m_commandsToRunOnTemporaryBreak.clear();
|
||||
m_cookieForToken.clear();
|
||||
@@ -287,10 +278,8 @@ void GdbEngine::initializeVariables()
|
||||
|
||||
// FIXME: unhandled:
|
||||
//m_outputCodecState = QTextCodec::ConverterState();
|
||||
//OutputCollector m_outputCollector;
|
||||
//QProcess m_gdbAdapter;
|
||||
//QProcess m_uploadProc;
|
||||
//Core::Utils::ConsoleProcess m_stubProc;
|
||||
}
|
||||
|
||||
void GdbEngine::gdbProcError(QProcess::ProcessError error)
|
||||
@@ -544,11 +533,13 @@ void GdbEngine::handleResponse(const QByteArray &buff)
|
||||
}
|
||||
|
||||
case '~': {
|
||||
static QRegExp re(_("New .hread 0x[0-9a-f]* \\(LWP ([0-9]*)\\)"));
|
||||
QByteArray data = GdbMi::parseCString(from, to);
|
||||
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))));
|
||||
}
|
||||
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()
|
||||
{
|
||||
qWarning() << "Unexpected gdb stderr:" << m_gdbAdapter->readAllStandardError();
|
||||
@@ -717,6 +689,18 @@ void GdbEngine::maybeHandleInferiorPidChanged(const QString &pid0)
|
||||
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,
|
||||
const char *callbackName, const QVariant &cookie)
|
||||
{
|
||||
@@ -727,28 +711,32 @@ void GdbEngine::postCommand(const QString &command, GdbCommandFlags flags,
|
||||
GdbCommandCallback callback, const char *callbackName,
|
||||
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;
|
||||
cmd.command = command;
|
||||
cmd.flags = flags;
|
||||
cmd.callback = callback;
|
||||
cmd.callbackName = callbackName;
|
||||
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) {
|
||||
// queue the commands that we cannot send at once
|
||||
QTC_ASSERT(status() == DebuggerInferiorRunning,
|
||||
@@ -757,13 +745,14 @@ void GdbEngine::postCommand(const QString &command, GdbCommandFlags flags,
|
||||
debugMessage(_("QUEUING COMMAND ") + cmd.command);
|
||||
m_commandsToRunOnTemporaryBreak.append(cmd);
|
||||
interruptInferior();
|
||||
} else if (!command.isEmpty()) {
|
||||
} else if (!cmd.command.isEmpty()) {
|
||||
flushCommand(cmd);
|
||||
}
|
||||
}
|
||||
|
||||
void GdbEngine::flushCommand(GdbCommand &cmd)
|
||||
void GdbEngine::flushCommand(const GdbCommand &cmd0)
|
||||
{
|
||||
GdbCommand cmd = cmd0;
|
||||
if (m_gdbAdapter->state() != QProcess::Running) {
|
||||
emit gdbInputAvailable(LogInput, 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);
|
||||
|
||||
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) {
|
||||
--m_pendingRequests;
|
||||
@@ -855,10 +846,13 @@ void GdbEngine::handleResultRecord(const GdbResultRecord &record)
|
||||
// An optimization would be requesting the continue immediately when the
|
||||
// event loop is entered, and let individual commands have a flag to suppress
|
||||
// that behavior.
|
||||
if (m_cookieForToken.isEmpty() && m_autoContinue) {
|
||||
m_autoContinue = false;
|
||||
continueInferior();
|
||||
showStatusMessage(tr("Continuing after temporary stop."));
|
||||
if (m_continuationAfterDone && m_cookieForToken.isEmpty()) {
|
||||
Continuation cont = m_continuationAfterDone;
|
||||
m_continuationAfterDone = 0;
|
||||
(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)
|
||||
{
|
||||
const QByteArray &reason = data.findChild("reason").data();
|
||||
const QByteArray reason = data.findChild("reason").data();
|
||||
|
||||
if (isExitedReason(reason)) {
|
||||
qq->notifyInferiorExited();
|
||||
@@ -1107,7 +1101,7 @@ void GdbEngine::handleAsyncOutput(const GdbMi &data)
|
||||
|
||||
qq->notifyInferiorStopped();
|
||||
handleAqcuiredInferior();
|
||||
m_autoContinue = true;
|
||||
// FIXME: m_continuationAfterDone = true;
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1123,7 +1117,7 @@ void GdbEngine::handleAsyncOutput(const GdbMi &data)
|
||||
flushCommand(cmd);
|
||||
}
|
||||
showStatusMessage(tr("Processing queued commands."));
|
||||
m_autoContinue = true;
|
||||
// FIXME: m_continuationAfterDone = true;
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1185,64 +1179,12 @@ void GdbEngine::handleAsyncOutput(const GdbMi &data)
|
||||
}
|
||||
|
||||
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);
|
||||
postCommand(_("p 0"), CB(handleAsyncOutput2), var); // dummy
|
||||
QVariant var = QVariant::fromValue<GdbMi>(data);
|
||||
if (m_debuggingHelperState == DebuggingHelperUninitialized) {
|
||||
tryLoadDebuggingHelpers();
|
||||
postCommand(_("p 4"), CB(handleStop1), 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)));
|
||||
handleAsyncOutput2(data);
|
||||
handleStop1(GdbResultRecord(), var);
|
||||
}
|
||||
return;
|
||||
}
|
||||
@@ -1296,12 +1238,77 @@ void GdbEngine::reloadStack()
|
||||
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();
|
||||
|
||||
@@ -1399,6 +1406,7 @@ void GdbEngine::handleFileExecAndSymbols(const GdbResultRecord &response, const
|
||||
}
|
||||
}
|
||||
|
||||
#if 0
|
||||
void GdbEngine::handleExecRun(const GdbResultRecord &response, const QVariant &)
|
||||
{
|
||||
if (response.resultClass == GdbResultRunning) {
|
||||
@@ -1413,6 +1421,7 @@ void GdbEngine::handleExecRun(const GdbResultRecord &response, const QVariant &)
|
||||
qq->notifyInferiorExited();
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
void GdbEngine::handleExecContinue(const GdbResultRecord &response, const QVariant &)
|
||||
{
|
||||
@@ -1519,6 +1528,7 @@ void GdbEngine::handleExitHelper(const GdbResultRecord &, const QVariant &)
|
||||
|
||||
void GdbEngine::exitDebugger2()
|
||||
{
|
||||
/*
|
||||
postCommand(_("-gdb-exit"), CB(handleExit));
|
||||
// 20s can easily happen when loading webkit debug information
|
||||
if (!m_gdbAdapter->waitForFinished(20000)) {
|
||||
@@ -1533,6 +1543,7 @@ void GdbEngine::exitDebugger2()
|
||||
.arg(m_gdbAdapter->state()));
|
||||
m_gdbAdapter->kill();
|
||||
}
|
||||
*/
|
||||
|
||||
m_outputCollector.shutdown();
|
||||
initializeVariables();
|
||||
@@ -1548,6 +1559,8 @@ int GdbEngine::currentFrame() const
|
||||
void GdbEngine::startDebugger(const DebuggerStartParametersPtr &sp)
|
||||
{
|
||||
m_startParameters = sp;
|
||||
m_gdbAdapter->startAdapter(sp);
|
||||
/*
|
||||
// This should be set by the constructor or in exitDebugger().
|
||||
QTC_ASSERT(m_debuggingHelperState == DebuggingHelperUninitialized,
|
||||
initializeVariables());
|
||||
@@ -1619,154 +1632,7 @@ void GdbEngine::startDebugger(const DebuggerStartParametersPtr &sp)
|
||||
QString loc = theDebuggerStringSetting(GdbLocation);
|
||||
showStatusMessage(tr("Starting Debugger: ") + loc + _c(' ') + gdbArgs.join(_(" ")));
|
||||
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()
|
||||
@@ -1777,32 +1643,6 @@ void GdbEngine::continueInferior()
|
||||
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 &)
|
||||
{
|
||||
qq->notifyInferiorStopped();
|
||||
@@ -1850,7 +1690,7 @@ void GdbEngine::handleTargetRemote(const GdbResultRecord &record, const QVariant
|
||||
if (record.resultClass == GdbResultDone) {
|
||||
//postCommand(_("-exec-continue"), CB(handleExecContinue));
|
||||
handleAqcuiredInferior();
|
||||
m_autoContinue = true;
|
||||
// FIXME m_continuationAfterDone = true;
|
||||
} else if (record.resultClass == GdbResultError) {
|
||||
// 16^error,msg="hd:5555: Connection timed out."
|
||||
QString msg = __(record.data.findChild("msg").data());
|
||||
@@ -1899,8 +1739,15 @@ void GdbEngine::nextExec()
|
||||
qq->notifyInferiorRunningRequested();
|
||||
if (qq->isReverseDebugging())
|
||||
postCommand(_("-reverse-next"), CB(handleExecContinue));
|
||||
else
|
||||
else {
|
||||
#if 0
|
||||
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()
|
||||
@@ -3478,7 +3325,7 @@ void GdbEngine::handleDebuggingHelperValue1(const GdbResultRecord &record,
|
||||
&& msg.startsWith(__("The program being debugged stopped while"))
|
||||
&& msg.contains(__("qDumpObjectData440"))) {
|
||||
// Fake full stop
|
||||
postCommand(_("p 0"), CB(handleAsyncOutput2)); // dummy
|
||||
postCommand(_("p 0"), CB(handleStop2)); // dummy
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
@@ -4287,14 +4134,209 @@ void GdbEngine::handleFetchDisassemblerByAddress0(const GdbResultRecord &record,
|
||||
|
||||
void GdbEngine::gotoLocation(const StackFrame &frame, bool setMarker)
|
||||
{
|
||||
lastFile = frame.file;
|
||||
lastLine = frame.line;
|
||||
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,
|
||||
QList<Core::IOptionsPage*> *opts)
|
||||
{
|
||||
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,
|
||||
@@ -4305,8 +4347,9 @@ IDebuggerEngine *createSymbianEngine(DebuggerManager *parent,
|
||||
|
||||
if (!qgetenv("QTCREATOR_WITH_S60").isEmpty())
|
||||
opts->push_back(new TrkOptionsPage(options));
|
||||
TrkGdbAdapter *adapter = new TrkGdbAdapter(options);
|
||||
GdbEngine *engine = new GdbEngine(parent, adapter);
|
||||
GdbEngine *engine = new GdbEngine(parent);
|
||||
TrkGdbAdapter *adapter = new TrkGdbAdapter(engine, options);
|
||||
engine->setGdbAdapter(adapter);
|
||||
QObject::connect(adapter, SIGNAL(output(QString)),
|
||||
parent, SLOT(showDebuggerOutput(QString)));
|
||||
return engine;
|
||||
|
||||
@@ -33,11 +33,8 @@
|
||||
#include "idebuggerengine.h"
|
||||
#include "debuggermanager.h" // only for StartParameters
|
||||
#include "gdbmi.h"
|
||||
#include "abstractgdbadapter.h"
|
||||
#include "outputcollector.h"
|
||||
#include "watchutils.h"
|
||||
|
||||
#include <consoleprocess.h>
|
||||
#include "outputcollector.h"
|
||||
|
||||
#include <QtCore/QByteArray>
|
||||
#include <QtCore/QHash>
|
||||
@@ -45,6 +42,7 @@
|
||||
#include <QtCore/QObject>
|
||||
#include <QtCore/QProcess>
|
||||
#include <QtCore/QPoint>
|
||||
#include <QtCore/QSet>
|
||||
#include <QtCore/QTextCodec>
|
||||
#include <QtCore/QTime>
|
||||
#include <QtCore/QVariant>
|
||||
@@ -58,7 +56,7 @@ QT_END_NAMESPACE
|
||||
namespace Debugger {
|
||||
namespace Internal {
|
||||
|
||||
|
||||
class AbstractGdbAdapter;
|
||||
class DebuggerManager;
|
||||
class IDebuggerManagerAccessForEngines;
|
||||
class GdbResultRecord;
|
||||
@@ -75,52 +73,14 @@ enum DebuggingHelperState
|
||||
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
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
GdbEngine(DebuggerManager *parent, AbstractGdbAdapter *gdbAdapter);
|
||||
explicit GdbEngine(DebuggerManager *parent);
|
||||
~GdbEngine();
|
||||
void setGdbAdapter(AbstractGdbAdapter *adapter);
|
||||
|
||||
signals:
|
||||
void gdbInputAvailable(int channel, const QString &msg);
|
||||
@@ -145,7 +105,6 @@ private:
|
||||
void shutdown();
|
||||
void setToolTipExpression(const QPoint &mousePos, TextEditor::ITextEditor *editor, int cursorPos);
|
||||
void startDebugger(const DebuggerStartParametersPtr &sp);
|
||||
Q_SLOT void startDebugger2();
|
||||
void exitDebugger();
|
||||
void exitDebugger2();
|
||||
void detachDebugger();
|
||||
@@ -217,14 +176,20 @@ public: // otherwise the Qt flag macros are unhappy
|
||||
|
||||
|
||||
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
|
||||
{
|
||||
GdbCommand() : flags(0), callback(0), callbackName(0) {}
|
||||
GdbCommand()
|
||||
: flags(0), callback(0), adapterCallback(0), callbackName(0)
|
||||
{}
|
||||
|
||||
int flags;
|
||||
GdbCommandCallback callback;
|
||||
AdapterCallback adapterCallback;
|
||||
const char *callbackName;
|
||||
QString command;
|
||||
QVariant cookie;
|
||||
@@ -235,7 +200,7 @@ private:
|
||||
// queue". resultNeeded == true increments m_pendingResults on
|
||||
// send and decrements on receipt, effectively preventing
|
||||
// watch model updates before everything is finished.
|
||||
void flushCommand(GdbCommand &cmd);
|
||||
void flushCommand(const GdbCommand &cmd);
|
||||
void postCommand(const QString &command,
|
||||
GdbCommandFlags flags,
|
||||
GdbCommandCallback callback = 0,
|
||||
@@ -245,7 +210,11 @@ private:
|
||||
GdbCommandCallback callback = 0,
|
||||
const char *callbackName = 0,
|
||||
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 updateLocals();
|
||||
@@ -257,25 +226,36 @@ private slots:
|
||||
void readUploadStandardOutput();
|
||||
void readUploadStandardError();
|
||||
void readDebugeeOutput(const QByteArray &data);
|
||||
void stubStarted();
|
||||
void stubError(const QString &msg);
|
||||
void uploadProcError(QProcess::ProcessError error);
|
||||
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:
|
||||
int terminationIndex(const QByteArray &buffer, int &length);
|
||||
void handleResponse(const QByteArray &buff);
|
||||
void handleStart(const GdbResultRecord &response, const QVariant &);
|
||||
void handleAttach(const GdbResultRecord &, const QVariant &);
|
||||
void handleStubAttached(const GdbResultRecord &, const QVariant &);
|
||||
void handleAqcuiredInferior();
|
||||
void handleAsyncOutput2(const GdbResultRecord &, const QVariant &cookie);
|
||||
void handleAsyncOutput2(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 handleFileExecAndSymbols(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 handleExecRunToFunction(const GdbResultRecord &response, const QVariant &);
|
||||
void handleInfoShared(const GdbResultRecord &response, const QVariant &);
|
||||
@@ -306,7 +286,6 @@ private:
|
||||
QList<WatchData> *insertions);
|
||||
const bool m_dumperInjectionLoad;
|
||||
|
||||
OutputCollector m_outputCollector;
|
||||
QTextCodec *m_outputCodec;
|
||||
QTextCodec::ConverterState m_outputCodecState;
|
||||
|
||||
@@ -315,8 +294,6 @@ private:
|
||||
AbstractGdbAdapter *m_gdbAdapter;
|
||||
QProcess m_uploadProc;
|
||||
|
||||
Core::Utils::ConsoleProcess m_stubProc;
|
||||
|
||||
QHash<int, GdbCommand> m_cookieForToken;
|
||||
QHash<int, QByteArray> m_customOutputForToken;
|
||||
|
||||
@@ -448,7 +425,11 @@ private:
|
||||
QString m_currentFrame;
|
||||
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_modulesListOutdated;
|
||||
|
||||
@@ -458,6 +439,8 @@ private:
|
||||
IDebuggerManagerAccessForEngines * const qq;
|
||||
DebuggerStartParametersPtr m_startParameters;
|
||||
// make sure to re-initialize new members in initializeVariables();
|
||||
public:
|
||||
OutputCollector m_outputCollector;
|
||||
};
|
||||
|
||||
} // 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 Internal {
|
||||
|
||||
TrkGdbAdapter::TrkGdbAdapter(const TrkOptionsPtr &options) :
|
||||
TrkGdbAdapter::TrkGdbAdapter(GdbEngine *engine, const TrkOptionsPtr &options) :
|
||||
AbstractGdbAdapter(engine),
|
||||
m_options(options),
|
||||
m_running(false),
|
||||
m_gdbAckMode(true),
|
||||
@@ -216,19 +217,22 @@ QByteArray TrkGdbAdapter::trkStepRangeMessage(byte option)
|
||||
return ba;
|
||||
}
|
||||
|
||||
void TrkGdbAdapter::startInferior()
|
||||
void TrkGdbAdapter::startInferiorEarly()
|
||||
{
|
||||
QString errorMessage;
|
||||
const QString device = effectiveTrkDevice();
|
||||
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
|
||||
if (m_waitCount++ < (m_options->mode == TrkOptions::BlueTooth ? 60 : 5)) {
|
||||
QTimer::singleShot(1000, this, SLOT(startInferior()));
|
||||
QTimer::singleShot(1000, this, SLOT(startInferiorEarly()));
|
||||
} else {
|
||||
emit output(QString::fromLatin1("Failed to connect to %1 after %2 attempts").arg(device).arg(m_waitCount));
|
||||
emit finished(-44, QProcess::CrashExit);
|
||||
QString msg = QString::fromLatin1("Failed to connect to %1 after "
|
||||
"%2 attempts").arg(device).arg(m_waitCount);
|
||||
logMessage(msg);
|
||||
emit adapterStartFailed(msg);
|
||||
}
|
||||
QTimer::singleShot(1000, this, SLOT(startInferiorEarly()));
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1292,38 +1296,43 @@ void TrkGdbAdapter::interruptInferior()
|
||||
|
||||
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)
|
||||
{
|
||||
emit output(QString("GDB: ProcessFinished %1 %2").arg(exitCode).arg(exitStatus));
|
||||
logMessage(QString("GDB: ProcessFinished %1 %2").arg(exitCode).arg(exitStatus));
|
||||
}
|
||||
|
||||
void TrkGdbAdapter::handleGdbStarted()
|
||||
{
|
||||
emit output(QString("GDB: Process Started"));
|
||||
emit started();
|
||||
logMessage(QString("GDB: Process Started"));
|
||||
emit adapterStarted();
|
||||
}
|
||||
|
||||
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) {
|
||||
const QString device = effectiveTrkDevice();
|
||||
const QString blueToothListener = QLatin1String("rfcomm");
|
||||
emit output(QString::fromLatin1("### Starting BlueTooth listener %1 on %2").arg(blueToothListener, device));
|
||||
m_rfcommProc.start(blueToothListener + QLatin1String(" -r listen ") + m_options->blueToothDevice + QLatin1String(" 1"));
|
||||
logMessage(QString::fromLatin1("### Starting BlueTooth listener %1 on %2")
|
||||
.arg(blueToothListener, device));
|
||||
m_rfcommProc.start(blueToothListener + QLatin1String(" -r listen ")
|
||||
+ m_options->blueToothDevice + QLatin1String(" 1"));
|
||||
m_rfcommProc.waitForStarted();
|
||||
if (m_rfcommProc.state() != QProcess::Running) {
|
||||
const QString msg = QString::fromLocal8Bit(m_rfcommProc.readAllStandardError());
|
||||
emit output(QString::fromLatin1("Failed to start BlueTooth listener %1 on %2: %3\n%4").arg(blueToothListener, device, m_rfcommProc.errorString(), msg));
|
||||
emit finished(-44, QProcess::CrashExit);
|
||||
QString msg = QString::fromLatin1("Failed to start BlueTooth "
|
||||
"listener %1 on %2: %3\n");
|
||||
msg = msg.arg(blueToothListener, device, m_rfcommProc.errorString());
|
||||
msg += QString::fromLocal8Bit(m_rfcommProc.readAllStandardError());
|
||||
emit adapterStartFailed(msg);
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -1334,7 +1343,19 @@ void TrkGdbAdapter::run()
|
||||
connect(&m_trkDevice, SIGNAL(error(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
|
||||
@@ -1363,9 +1384,10 @@ static void setGdbCygwinEnvironment(const QString &cygwin, QProcess *process)
|
||||
void TrkGdbAdapter::startGdb()
|
||||
{
|
||||
if (!m_gdbServer.listen(QHostAddress(gdbServerIP()), gdbServerPort())) {
|
||||
logMessage(QString("Unable to start the gdb server at %1: %2.")
|
||||
.arg(m_gdbServerName).arg(m_gdbServer.errorString()));
|
||||
emit finished(-45, QProcess::CrashExit);
|
||||
QString msg = QString("Unable to start the gdb server at %1: %2.")
|
||||
.arg(m_gdbServerName).arg(m_gdbServer.errorString());
|
||||
logMessage(msg);
|
||||
emit adapterStartFailed(msg);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1376,7 +1398,7 @@ void TrkGdbAdapter::startGdb()
|
||||
this, SLOT(handleGdbConnection()));
|
||||
|
||||
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;
|
||||
gdbArgs.append(QLatin1String("--nx")); // Do not read .gdbinit file
|
||||
gdbArgs.append(QLatin1String("-i"));
|
||||
@@ -1405,52 +1427,44 @@ void TrkGdbAdapter::sendGdbMessage(const QString &msg, GdbCallback callback,
|
||||
void TrkGdbAdapter::handleRfcommReadyReadStandardError()
|
||||
{
|
||||
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()
|
||||
{
|
||||
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)
|
||||
{
|
||||
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)
|
||||
{
|
||||
emit output(QString("RFCOMM: ProcessFinished %1 %2").arg(exitCode).arg(exitStatus));
|
||||
logMessage(QString("RFCOMM: ProcessFinished %1 %2").arg(exitCode).arg(exitStatus));
|
||||
}
|
||||
|
||||
void TrkGdbAdapter::handleRfcommStarted()
|
||||
{
|
||||
emit output(QString("RFCOMM: Process Started"));
|
||||
logMessage(QString("RFCOMM: Process Started"));
|
||||
}
|
||||
|
||||
void TrkGdbAdapter::handleRfcommStateChanged(QProcess::ProcessState newState)
|
||||
{
|
||||
emit output(QString("RFCOMM: Process State %1").arg(newState));
|
||||
logMessage(QString("RFCOMM: Process State %1").arg(newState));
|
||||
}
|
||||
|
||||
//
|
||||
// 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()
|
||||
{
|
||||
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_gdbProc.kill();
|
||||
}
|
||||
@@ -1509,6 +1523,17 @@ void TrkGdbAdapter::setEnvironment(const QStringList &env)
|
||||
m_gdbProc.setEnvironment(env);
|
||||
}
|
||||
|
||||
void TrkGdbAdapter::shutdownAdapter()
|
||||
{
|
||||
emit adapterShutDown();
|
||||
}
|
||||
|
||||
void TrkGdbAdapter::shutdownInferior()
|
||||
{
|
||||
emit inferiorShutDown();
|
||||
}
|
||||
|
||||
/*
|
||||
void TrkGdbAdapter::attach()
|
||||
{
|
||||
#ifdef STANDALONE_RUNNER
|
||||
@@ -1522,6 +1547,7 @@ void TrkGdbAdapter::attach()
|
||||
m_engine->postCommand(_("target remote ") + gdbServerName());
|
||||
#endif
|
||||
}
|
||||
*/
|
||||
|
||||
} // namespace Internal
|
||||
} // namespace Debugger
|
||||
|
||||
@@ -71,7 +71,7 @@ public:
|
||||
typedef trk::Callback<const GdbResult &> GdbCallback;
|
||||
typedef QSharedPointer<TrkOptions> TrkOptionsPtr;
|
||||
|
||||
explicit TrkGdbAdapter(const TrkOptionsPtr &options);
|
||||
TrkGdbAdapter(GdbEngine *engine, const TrkOptionsPtr &options);
|
||||
~TrkGdbAdapter();
|
||||
void setGdbServerName(const QString &name);
|
||||
QString gdbServerName() const { return m_gdbServerName; }
|
||||
@@ -80,22 +80,14 @@ public:
|
||||
void setVerbose(int verbose) { m_verbose = verbose; }
|
||||
void setBufferedMemoryRead(bool b) { m_bufferedMemoryRead = b; }
|
||||
trk::Session &session() { return m_session; }
|
||||
void startGdb();
|
||||
|
||||
// Set a device (from the project) to override the settings.
|
||||
QString overrideTrkDevice() const;
|
||||
void setOverrideTrkDevice(const QString &);
|
||||
|
||||
public slots:
|
||||
void startInferior();
|
||||
void run();
|
||||
|
||||
signals:
|
||||
void output(const QString &msg);
|
||||
void startSuccessful();
|
||||
void startFailed();
|
||||
|
||||
private slots:
|
||||
void startGdb();
|
||||
|
||||
private:
|
||||
friend class RunnerGui;
|
||||
@@ -108,6 +100,7 @@ private:
|
||||
QProcess m_gdbProc;
|
||||
QProcess m_rfcommProc;
|
||||
bool m_running;
|
||||
DebuggerStartParametersPtr m_startParameters;
|
||||
|
||||
public:
|
||||
//
|
||||
@@ -126,8 +119,15 @@ public:
|
||||
void setWorkingDirectory(const QString &dir);
|
||||
void setEnvironment(const QStringList &env);
|
||||
bool isAdapter() const { return true; }
|
||||
void attach();
|
||||
//void attach();
|
||||
void interruptInferior();
|
||||
void startInferiorEarly();
|
||||
|
||||
void startAdapter(const DebuggerStartParametersPtr &sp);
|
||||
void prepareInferior();
|
||||
void startInferior();
|
||||
void shutdownInferior();
|
||||
void shutdownAdapter();
|
||||
|
||||
//
|
||||
// TRK
|
||||
|
||||
@@ -41,7 +41,7 @@
|
||||
|
||||
#include "qmljsastvisitor_p.h"
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
QT_QML_BEGIN_NAMESPACE
|
||||
|
||||
namespace QmlJS { namespace AST {
|
||||
|
||||
@@ -55,4 +55,4 @@ Visitor::~Visitor()
|
||||
|
||||
} } // namespace QmlJS::AST
|
||||
|
||||
QT_END_NAMESPACE
|
||||
QT_QML_END_NAMESPACE
|
||||
|
||||
Reference in New Issue
Block a user