Commit 378036c9 authored by hjk's avatar hjk

debugger: make attaching to running process work again

parent d24752a7
......@@ -248,6 +248,7 @@ AttachExternalDialog::AttachExternalDialog(QWidget *parent)
QPushButton *refreshButton = new QPushButton(tr("Refresh"));
connect(refreshButton, SIGNAL(clicked()), this, SLOT(rebuildProcessList()));
m_ui->buttonBox->addButton(refreshButton, QDialogButtonBox::ActionRole);
m_ui->filterLineEdit->setFocus(Qt::TabFocusReason);
// Do not use activated, will be single click in Oxygen
connect(m_ui->procView, SIGNAL(doubleClicked(QModelIndex)),
......
......@@ -366,6 +366,7 @@ private:
ThreadsHandler *threadsHandler() { return m_threadsHandler; }
WatchHandler *watchHandler() { return m_watchHandler; }
SourceFilesWindow *sourceFileWindow() { return m_sourceFilesWindow; }
QWidget *threadsWindow() const { return m_threadsWindow; }
void notifyInferiorStopped();
void notifyInferiorRunningRequested();
......@@ -376,20 +377,16 @@ private:
void cleanupViews();
//
// Implementation of IDebuggerManagerAccessForDebugMode
//
QWidget *threadsWindow() const { return m_threadsWindow; }
virtual bool qtDumperLibraryEnabled() const;
virtual QString qtDumperLibraryName() const;
virtual QStringList qtDumperLibraryLocations() const;
virtual void showQtDumperLibraryWarning(const QString &details = QString());
virtual bool isReverseDebugging() const;
//
// internal implementation
//
bool qtDumperLibraryEnabled() const;
QString qtDumperLibraryName() const;
QStringList qtDumperLibraryLocations() const;
void showQtDumperLibraryWarning(const QString &details = QString());
bool isReverseDebugging() const;
QAbstractItemModel *threadsModel();
Q_SLOT void loadSessionData();
Q_SLOT void saveSessionData();
Q_SLOT void dumpLog();
......@@ -397,7 +394,6 @@ private:
public:
// stuff in this block should be made private by moving it to
// one of the interfaces
QAbstractItemModel *threadsModel();
int status() const { return m_status; }
// FIXME: hide this in the engines?
//DebuggerStartMode startMode() const;
......@@ -471,14 +467,12 @@ private:
QAction *m_watchAction;
QAction *m_breakAction;
QAction *m_sepAction;
//QActio *m_stepByInstructionAction;
QAction *m_reverseDirectionAction;
QWidget *m_breakWindow;
QWidget *m_localsWindow;
QWidget *m_registerWindow;
QWidget *m_modulesWindow;
//QWidget *m_tooltipWindow;
QWidget *m_stackWindow;
QWidget *m_threadsWindow;
QWidget *m_watchersWindow;
......
......@@ -1229,7 +1229,7 @@ void DebuggerPlugin::attachExternalApplication(qint64 pid, const QString &crashP
const DebuggerStartParametersPtr sp(new DebuggerStartParameters);
sp->attachPID = pid;
sp->crashParameter = crashParameter;
sp->startMode = crashParameter.isEmpty() ? AttachExternal : AttachCrashedExternal;
sp->startMode = crashParameter.isEmpty() ? AttachExternal : AttachCrashedExternal;
RunConfigurationPtr rc = activeRunConfiguration();
if (rc.isNull())
rc = DebuggerRunner::createDefaultRunConfiguration();
......
/**************************************************************************
**
** 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 "attachgdbadapter.h"
#include "debuggeractions.h"
#include "gdbengine.h"
#include "procinterrupt.h"
#include <utils/qtcassert.h>
namespace Debugger {
namespace Internal {
#define STRINGIFY_INTERNAL(x) #x
#define STRINGIFY(x) STRINGIFY_INTERNAL(x)
#define CB(callback) \
static_cast<GdbEngine::AdapterCallback>(&AttachGdbAdapter::callback), \
STRINGIFY(callback)
///////////////////////////////////////////////////////////////////////
//
// AttachGdbAdapter
//
///////////////////////////////////////////////////////////////////////
AttachGdbAdapter::AttachGdbAdapter(GdbEngine *engine, QObject *parent)
: AbstractGdbAdapter(engine, parent)
{
QTC_ASSERT(state() == AdapterNotRunning, qDebug() << state());
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, SLOT(handleGdbStarted()));
connect(&m_gdbProc, SIGNAL(finished(int, QProcess::ExitStatus)),
this, SLOT(handleGdbFinished(int, QProcess::ExitStatus)));
}
void AttachGdbAdapter::startAdapter()
{
QTC_ASSERT(state() == AdapterNotRunning, qDebug() << state());
setState(AdapterStarting);
debugMessage(_("TRYING TO START ADAPTER"));
QStringList gdbArgs;
gdbArgs.prepend(_("mi"));
gdbArgs.prepend(_("-i"));
if (!m_engine->m_outputCollector.listen()) {
emit adapterStartFailed(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 (!startParameters().workingDir.isEmpty())
setWorkingDirectory(startParameters().workingDir);
if (!startParameters().environment.isEmpty())
setEnvironment(startParameters().environment);
QString location = theDebuggerStringSetting(GdbLocation);
m_gdbProc.start(location, gdbArgs);
}
void AttachGdbAdapter::handleGdbStarted()
{
QTC_ASSERT(state() == AdapterStarting, qDebug() << state());
setState(AdapterStarted);
emit adapterStarted();
}
void AttachGdbAdapter::prepareInferior()
{
const qint64 pid = startParameters().attachPID;
QTC_ASSERT(state() == AdapterStarted, qDebug() << state());
setState(InferiorPreparing);
qDebug() << "USING " << pid;
m_engine->postCommand(_("attach %1").arg(pid), CB(handleAttach));
// Task 254674 does not want to remove them
//qq->breakHandler()->removeAllBreakpoints();
}
void AttachGdbAdapter::handleAttach(const GdbResultRecord &response, const QVariant &)
{
QTC_ASSERT(state() == InferiorPreparing, qDebug() << state());
if (response.resultClass == GdbResultDone) {
setState(InferiorPrepared);
emit inferiorPrepared();
} else if (response.resultClass == GdbResultError) {
QString msg = __(response.data.findChild("msg").data());
setState(InferiorPreparationFailed);
emit inferiorPreparationFailed(msg);
}
}
void AttachGdbAdapter::startInferior()
{
QTC_ASSERT(state() == InferiorPrepared, qDebug() << state());
setState(InferiorStarting);
m_engine->postCommand(_("-exec-continue"), CB(handleContinue));
}
void AttachGdbAdapter::handleContinue(const GdbResultRecord &response, const QVariant &)
{
QTC_ASSERT(state() == InferiorStarting, qDebug() << state());
if (response.resultClass == GdbResultRunning) {
setState(InferiorStarted);
emit inferiorStarted();
} else {
QTC_ASSERT(response.resultClass == GdbResultError, /**/);
const QByteArray &msg = response.data.findChild("msg").data();
setState(InferiorStartFailed);
emit inferiorStartFailed(msg);
}
}
void AttachGdbAdapter::interruptInferior()
{
debugMessage(_("TRYING TO INTERUPT INFERIOR"));
const qint64 pid = startParameters().attachPID;
if (!interruptProcess(pid))
debugMessage(_("CANNOT INTERRUPT %1").arg(pid));
}
void AttachGdbAdapter::shutdown()
{
if (state() == InferiorStarted) {
setState(InferiorShuttingDown);
m_engine->postCommand(_("detach"), CB(handleDetach));
return;
}
if (state() == InferiorShutDown) {
setState(AdapterShuttingDown);
m_engine->postCommand(_("-gdb-exit"), CB(handleExit));
return;
}
QTC_ASSERT(state() == AdapterNotRunning, qDebug() << state());
}
void AttachGdbAdapter::handleDetach(const GdbResultRecord &response, const QVariant &)
{
if (response.resultClass == GdbResultDone) {
setState(InferiorShutDown);
emit inferiorShutDown();
shutdown(); // re-iterate...
} else if (response.resultClass == GdbResultError) {
QString msg = tr("Inferior process could not be stopped:\n") +
__(response.data.findChild("msg").data());
setState(InferiorShutdownFailed);
emit inferiorShutdownFailed(msg);
}
}
void AttachGdbAdapter::handleExit(const GdbResultRecord &response, const QVariant &)
{
if (response.resultClass == GdbResultDone) {
// don't set state here, this will be handled in handleGdbFinished()
} else if (response.resultClass == GdbResultError) {
QString msg = tr("Gdb process could not be stopped:\n") +
__(response.data.findChild("msg").data());
emit adapterShutdownFailed(msg);
}
}
void AttachGdbAdapter::handleGdbFinished(int, QProcess::ExitStatus)
{
debugMessage(_("GDB PROESS FINISHED"));
setState(AdapterNotRunning);
emit adapterShutDown();
}
} // namespace Internal
} // namespace Debugger
/**************************************************************************
**
** 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_ATTACHGDBADAPTER_H
#define DEBUGGER_ATTACHGDBADAPTER_H
#include "abstractgdbadapter.h"
#include "gdbengine.h"
#include <QtCore/QDebug>
#include <QtCore/QProcess>
namespace Debugger {
namespace Internal {
///////////////////////////////////////////////////////////////////////
//
// AttachGdbAdapter
//
///////////////////////////////////////////////////////////////////////
class AttachGdbAdapter : public AbstractGdbAdapter
{
Q_OBJECT
public:
AttachGdbAdapter(GdbEngine *engine, QObject *parent = 0);
private:
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 isTrkAdapter() const { return false; }
void startAdapter();
void prepareInferior();
void startInferior();
void interruptInferior();
void shutdown();
void handleAttach(const GdbResultRecord &, const QVariant &);
void handleContinue(const GdbResultRecord &, const QVariant &);
void handleDetach(const GdbResultRecord &, const QVariant &);
void handleExit(const GdbResultRecord &, const QVariant &);
void debugMessage(const QString &msg) { m_engine->debugMessage(msg); }
Q_SLOT void handleGdbFinished(int, QProcess::ExitStatus);
Q_SLOT void handleGdbStarted();
QProcess m_gdbProc;
};
} // namespace Internal
} // namespace Debugger
#endif // DEBUGGER_ATTACHDBADAPTER_H
......@@ -31,13 +31,10 @@
#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 {
......@@ -148,7 +145,7 @@ void CoreGdbAdapter::handleTargetCore(const GdbResultRecord &response, const QVa
if (response.resultClass == GdbResultDone) {
setState(InferiorStarted);
emit inferiorStarted();
m_engine->handleTargetCore();
m_engine->updateAll();
} else {
QTC_ASSERT(response.resultClass == GdbResultError, /**/);
const QByteArray &msg = response.data.findChild("msg").data();
......
include(../../../shared/trk/trk.pri)
HEADERS += \
$$PWD/abstractgdbadapter.h \
$$PWD/plaingdbadapter.h \
$$PWD/gdbmi.h \
$$PWD/gdbengine.h \
$$PWD/gdboptionspage.h \
$$PWD/remotegdbadapter.h \
$$PWD/coregdbadapter.h \
$$PWD/trkgdbadapter.h \
$$PWD/trkoptions.h \
$$PWD/trkoptionswidget.h \
$$PWD/trkoptionspage.h
$$PWD/trkoptionspage.h \
$$PWD/abstractgdbadapter.h \
$$PWD/attachgdbadapter.h \
$$PWD/coregdbadapter.h \
$$PWD/plaingdbadapter.h \
$$PWD/remotegdbadapter.h \
$$PWD/trkgdbadapter.h \
SOURCES += \
$$PWD/gdbmi.cpp \
$$PWD/gdbengine.cpp \
$$PWD/gdboptionspage.cpp \
$$PWD/plaingdbadapter.cpp \
$$PWD/remotegdbadapter.cpp \
$$PWD/coregdbadapter.cpp \
$$PWD/trkoptions.cpp \
$$PWD/trkoptionswidget.cpp \
$$PWD/trkoptionspage.cpp \
$$PWD/trkgdbadapter.cpp
$$PWD/attachgdbadapter.cpp \
$$PWD/coregdbadapter.cpp \
$$PWD/plaingdbadapter.cpp \
$$PWD/remotegdbadapter.cpp \
$$PWD/trkgdbadapter.cpp \
FORMS += $$PWD/gdboptionspage.ui \
$$PWD/trkoptionswidget.ui
......
......@@ -34,10 +34,11 @@
#include "trkoptions.h"
#include "trkoptionspage.h"
#include "attachgdbadapter.h"
#include "coregdbadapter.h"
#include "plaingdbadapter.h"
#include "trkgdbadapter.h"
#include "remotegdbadapter.h"
#include "coregdbadapter.h"
#include "trkgdbadapter.h"
#include "watchutils.h"
#include "debuggeractions.h"
......@@ -46,7 +47,6 @@
#include "debuggermanager.h"
#include "debuggertooltip.h"
#include "gdbmi.h"
#include "procinterrupt.h"
#include "breakhandler.h"
#include "moduleshandler.h"
......@@ -182,6 +182,7 @@ GdbEngine::GdbEngine(DebuggerManager *parent) :
m_trkAdapter = new TrkGdbAdapter(this, options);
m_remoteAdapter = new RemoteGdbAdapter(this);
m_coreAdapter = new CoreGdbAdapter(this);
m_attachAdapter = new AttachGdbAdapter(this);
// Output
connect(&m_outputCollector, SIGNAL(byteDelivery(QByteArray)),
......@@ -232,6 +233,7 @@ GdbEngine::~GdbEngine()
delete m_trkAdapter;
delete m_remoteAdapter;
delete m_coreAdapter;
delete m_attachAdapter;
}
void GdbEngine::connectAdapter()
......@@ -697,6 +699,7 @@ void GdbEngine::interruptInferior()
return;
}
debugMessage(_("TRYING TO INTERUPT INFERIOR"));
m_gdbAdapter->interruptInferior();
}
......@@ -898,7 +901,7 @@ void GdbEngine::executeDebuggerCommand(const QString &command)
m_gdbAdapter->write(command.toLatin1() + "\r\n");
}
void GdbEngine::handleTargetCore()
void GdbEngine::updateAll()
{
qq->notifyInferiorStopped();
showStatusMessage(tr("Core file loaded."));
......@@ -1505,7 +1508,9 @@ void GdbEngine::shutdown()
void GdbEngine::detachDebugger()
{
postCommand(_("detach"), CB(handleDetach));
//postCommand(_("detach"), CB(handleDetach));
QTC_ASSERT(startMode() == AttachExternal, /**/);
shutdown();
}
void GdbEngine::exitDebugger()
......@@ -1516,11 +1521,6 @@ void GdbEngine::exitDebugger()
m_gdbAdapter->shutdown();
}
void GdbEngine::handleDetach(const GdbResultRecord &, const QVariant &)
{
exitDebugger();
}
int GdbEngine::currentFrame() const
{
return qq->stackHandler()->currentIndex();
......@@ -1547,6 +1547,8 @@ void GdbEngine::startDebugger(const DebuggerStartParametersPtr &sp)
m_gdbAdapter = m_coreAdapter;
else if (sp->startMode == StartRemote)
m_gdbAdapter = m_remoteAdapter;
else if (sp->startMode == AttachExternal)
m_gdbAdapter = m_attachAdapter;
else
m_gdbAdapter = m_plainAdapter;
......@@ -4081,7 +4083,7 @@ void GdbEngine::handleAdapterStarted()
void GdbEngine::handleInferiorPreparationFailed(const QString &msg)
{
debugMessage(_("INFERIOR PREPARATION FAILD"));
debugMessage(_("INFERIOR PREPARATION FAILED"));
showMessageBox(QMessageBox::Critical,
tr("Inferior start preparation failed"), msg);
shutdown();
......
......@@ -62,13 +62,14 @@ class IDebuggerManagerAccessForEngines;
class GdbResultRecord;
class GdbMi;
class WatchData;
class BreakpointData;
class WatchData;
class AttachGdbAdapter;
class CoreGdbAdapter;
class PlainGdbAdapter;
class TrkGdbAdapter;
class RemoteGdbAdapter;
class CoreGdbAdapter;
class TrkGdbAdapter;
enum DebuggingHelperState
{
......@@ -92,10 +93,11 @@ signals:
void applicationOutputAvailable(const QString &output);
private:
friend class AttachGdbAdapter;
friend class CoreGdbAdapter;
friend class PlainGdbAdapter;
friend class TrkGdbAdapter;
friend class RemoteGdbAdapter;
friend class CoreGdbAdapter;
friend class TrkGdbAdapter;
//
// IDebuggerEngine implementation
......@@ -226,6 +228,7 @@ private:
void postCommandHelper(const GdbCommand &cmd);
void setTokenBarrier();
void updateAll();
void updateLocals();
private slots:
......@@ -268,11 +271,9 @@ private:
void handleQueryPwd(const GdbResultRecord &response, const QVariant &);
void handleQuerySources(const GdbResultRecord &response, const QVariant &);
void handleExit(const GdbResultRecord &, const QVariant &);
void handleDetach(const GdbResultRecord &, const QVariant &);
//void handleSetTargetAsync(const GdbResultRecord &, const QVariant &);
//void handleTargetRemote(const GdbResultRecord &, const QVariant &);
void handleWatchPoint(const GdbResultRecord &, const QVariant &);
void handleTargetCore();
bool showToolTip();
// Convenience
......@@ -441,10 +442,11 @@ private:
// only one of those is active at a given time, available in m_gdbAdapter
AbstractGdbAdapter *m_gdbAdapter; // pointer to one listed below
AttachGdbAdapter *m_attachAdapter; // owned
CoreGdbAdapter *m_coreAdapter; // owned
PlainGdbAdapter *m_plainAdapter; // owned
TrkGdbAdapter *m_trkAdapter; // owned
RemoteGdbAdapter *m_remoteAdapter; // owned
CoreGdbAdapter *m_coreAdapter; // owned
TrkGdbAdapter *m_trkAdapter; // owned
public:
void showMessageBox(int icon, const QString &title, const QString &text);
......
......@@ -225,11 +225,6 @@ void PlainGdbAdapter::startInferior()
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"));
......
......@@ -31,10 +31,8 @@
#include "debuggeractions.h"
#include "gdbengine.h"
#include "procinterrupt.h"
#include <utils/qtcassert.h>
#include <coreplugin/icore.h>
#include <QtCore/QFileInfo>
#include <QtGui/QMessageBox>
......@@ -229,20 +227,7 @@ void RemoteGdbAdapter::handleExecRun(const GdbResultRecord &response, const QVar
void RemoteGdbAdapter::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));
m_engine->postCommand(_("-exec-interrupt"));
}
void RemoteGdbAdapter::shutdown()
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!