debugger: rework startup logic

This commit is contained in:
hjk
2009-09-21 11:09:38 +02:00
parent ae2cfdaa53
commit 1d64e169b0
9 changed files with 923 additions and 466 deletions

View File

@@ -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

View File

@@ -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

View File

@@ -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;

View File

@@ -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

View 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

View 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

View File

@@ -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

View File

@@ -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

View File

@@ -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