Commit 99fdaf06 authored by hjk's avatar hjk

debuygger: make snapshots using true parallel engines

parent 574862ac
......@@ -35,6 +35,7 @@ HEADERS += breakhandler.h \
procinterrupt.h \
registerhandler.h \
registerwindow.h \
sessionengine.h \
stackframe.h \
stackhandler.h \
stackwindow.h \
......@@ -50,6 +51,7 @@ HEADERS += breakhandler.h \
debuggeruiswitcher.h \
debuggermainwindow.h \
threadshandler.h
SOURCES += breakhandler.cpp \
breakwindow.cpp \
breakwindow.h \
......@@ -82,6 +84,7 @@ SOURCES += breakhandler.cpp \
debuggeruiswitcher.cpp \
debuggermainwindow.cpp \
threadshandler.cpp \
sessionengine.cpp \
stackframe.cpp
FORMS += attachexternaldialog.ui \
......
......@@ -248,6 +248,7 @@ enum ModelRoles
RequestReloadRegistersRole,
// Snapshots
SnapshotCapabilityRole,
RequestMakeSnapshotRole,
RequestActivateSnapshotRole,
RequestRemoveSnapshotRole,
......
......@@ -224,7 +224,6 @@ public:
m_commandHandler(engine),
m_modulesHandler(engine),
m_registerHandler(engine),
m_snapshotHandler(engine),
m_sourceFilesHandler(engine),
m_stackHandler(engine),
m_threadsHandler(engine),
......@@ -291,7 +290,6 @@ public:
CommandHandler m_commandHandler;
ModulesHandler m_modulesHandler;
RegisterHandler m_registerHandler;
SnapshotHandler m_snapshotHandler;
SourceFilesHandler m_sourceFilesHandler;
StackHandler m_stackHandler;
ThreadsHandler m_threadsHandler;
......@@ -464,7 +462,7 @@ void DebuggerEngine::handleCommand(int role, const QVariant &value)
d->doShutdownInferior();
break;
case RequestExecSnapshotRole:
case RequestMakeSnapshotRole:
makeSnapshot();
break;
......@@ -575,10 +573,10 @@ WatchHandler *DebuggerEngine::watchHandler() const
return &d->m_watchHandler;
}
SnapshotHandler *DebuggerEngine::snapshotHandler() const
{
return &d->m_snapshotHandler;
}
//SnapshotHandler *DebuggerEngine::snapshotHandler() const
//{
// return &d->m_snapshotHandler;
//}
SourceFilesHandler *DebuggerEngine::sourceFilesHandler() const
{
......@@ -625,11 +623,6 @@ QAbstractItemModel *DebuggerEngine::returnModel() const
return d->m_watchHandler.model(ReturnWatch);
}
QAbstractItemModel *DebuggerEngine::snapshotModel() const
{
return d->m_snapshotHandler.model();
}
QAbstractItemModel *DebuggerEngine::sourceFilesModel() const
{
return d->m_sourceFilesHandler.model();
......
......@@ -105,7 +105,6 @@ class ModulesHandler;
class RegisterHandler;
class StackHandler;
class StackFrame;
class SnapshotHandler;
class SourceFilesHandler;
class ThreadsHandler;
class WatchHandler;
......@@ -154,7 +153,7 @@ public:
virtual QString qtNamespace() const { return QString(); }
virtual void makeSnapshot() {}
virtual void activateSnapshot(int index) { Q_UNUSED(index); }
virtual void updateAll() {}
virtual void attemptBreakpointSynchronization() {}
virtual void selectThread(int index) { Q_UNUSED(index); }
......@@ -197,7 +196,6 @@ public:
StackHandler *stackHandler() const;
ThreadsHandler *threadsHandler() const;
WatchHandler *watchHandler() const;
SnapshotHandler *snapshotHandler() const;
SourceFilesHandler *sourceFilesHandler() const;
QAbstractItemModel *commandModel() const;
......@@ -209,7 +207,7 @@ public:
QAbstractItemModel *localsModel() const;
QAbstractItemModel *watchersModel() const;
QAbstractItemModel *returnModel() const;
QAbstractItemModel *snapshotModel() const;
//QAbstractItemModel *snapshotModel() const;
QAbstractItemModel *sourceFilesModel() const;
void handleFinished();
......
......@@ -53,8 +53,8 @@
#include "watchutils.h"
#include "breakhandler.h"
#include "stackhandler.h"
#include "watchhandler.h"
#include "snapshothandler.h"
#include "sessionengine.h"
#ifdef Q_OS_WIN
# include "shared/peutils.h"
......@@ -820,43 +820,6 @@ static bool isCurrentProjectCppBased()
}
///////////////////////////////////////////////////////////////////////
//
// SessionEngine
//
///////////////////////////////////////////////////////////////////////
// This class contains data serving as a template for debugger engines
// started during a session.
class SessionEngine : public DebuggerEngine
{
public:
SessionEngine() : DebuggerEngine(DebuggerStartParameters()) {}
void setupEngine() {}
void setupInferior() {}
void runEngine() {}
void shutdownEngine() {}
void shutdownInferior() {}
bool isSessionEngine() const { return true; }
void loadSessionData()
{
breakHandler()->loadSessionData();
watchHandler()->loadSessionData();
}
void saveSessionData()
{
watchHandler()->saveSessionData();
breakHandler()->saveSessionData();
}
};
///////////////////////////////////////////////////////////////////////
//
// DebuggerPluginPrivate
......@@ -966,6 +929,7 @@ public slots:
DebuggerRunControl *createDebugger(const DebuggerStartParameters &sp);
void startDebugger(ProjectExplorer::RunControl *runControl);
void displayDebugger(ProjectExplorer::RunControl *runControl);
void dumpLog();
void cleanupViews();
......@@ -1146,6 +1110,7 @@ bool DebuggerPluginPrivate::initialize(const QStringList &arguments, QString *er
// Session related data
m_sessionEngine = new SessionEngine;
m_snapshotWindow->setModel(m_sessionEngine->m_snapshotHandler->model());
// Debug mode setup
m_debugMode = new DebugMode(this);
......@@ -1154,10 +1119,6 @@ bool DebuggerPluginPrivate::initialize(const QStringList &arguments, QString *er
connect(m_localsWindow->header(), SIGNAL(sectionResized(int,int,int)),
this, SLOT(updateWatchersHeader(int,int,int)), Qt::QueuedConnection);
// Tooltip
qRegisterMetaType<WatchData>("WatchData");
qRegisterMetaType<StackCookie>("StackCookie");
m_actions.continueAction = new QAction(tr("Continue"), this);
QIcon continueIcon = QIcon(":/debugger/images/debugger_continue_small.png");
continueIcon.addFile(":/debugger/images/debugger_continue.png");
......@@ -1950,29 +1911,41 @@ DebuggerPluginPrivate::createDebugger(const DebuggerStartParameters &sp)
return m_debuggerRunControlFactory->create(sp);
}
void DebuggerPluginPrivate::displayDebugger(ProjectExplorer::RunControl *rc)
{
DebuggerRunControl *runControl = qobject_cast<DebuggerRunControl *>(rc);
QTC_ASSERT(runControl, return);
disconnectEngine();
connectEngine(runControl->engine());
runControl->engine()->updateAll();
updateState(runControl->engine());
}
void DebuggerPluginPrivate::startDebugger(ProjectExplorer::RunControl *rc)
{
qDebug() << "START DEBUGGER 1";
QTC_ASSERT(rc, return);
DebuggerRunControl *runControl = qobject_cast<DebuggerRunControl *>(rc);
QTC_ASSERT(runControl, return);
activateDebugMode();
connectEngine(runControl->engine());
//m_sessionEngine->m_snapshotHandler->appendSnapshot(runControl);
ProjectExplorerPlugin::instance()->startRunControl(runControl, PE::DEBUGMODE);
qDebug() << "START DEBUGGER 2";
}
void DebuggerPluginPrivate::connectEngine(DebuggerEngine *engine)
{
//if (engine == m_sessionEngine)
// qDebug() << "CONNECTING DUMMY ENGINE" << engine;
//else
// qDebug() << "CONNECTING ENGINE " << engine;
if (engine == m_sessionEngine)
qDebug() << "CONNECTING DUMMY ENGINE" << engine;
else
qDebug() << "CONNECTING ENGINE " << engine;
m_breakWindow->setModel(engine->breakModel());
m_commandWindow->setModel(engine->commandModel());
m_localsWindow->setModel(engine->localsModel());
m_modulesWindow->setModel(engine->modulesModel());
m_registerWindow->setModel(engine->registerModel());
m_returnWindow->setModel(engine->returnModel());
m_snapshotWindow->setModel(engine->snapshotModel());
m_sourceFilesWindow->setModel(engine->sourceFilesModel());
m_stackWindow->setModel(engine->stackModel());
m_threadsWindow->setModel(engine->threadsModel());
......@@ -2666,6 +2639,11 @@ void DebuggerPlugin::startDebugger(ProjectExplorer::RunControl *runControl)
instance()->d->startDebugger(runControl);
}
void DebuggerPlugin::displayDebugger(ProjectExplorer::RunControl *runControl)
{
instance()->d->displayDebugger(runControl);
}
void DebuggerPlugin::updateState(DebuggerEngine *engine)
{
d->updateState(engine);
......@@ -2706,6 +2684,7 @@ void DebuggerPlugin::createNewDock(QWidget *widget)
void DebuggerPlugin::runControlStarted(DebuggerRunControl *runControl)
{
d->connectEngine(runControl->engine());
d->m_sessionEngine->m_snapshotHandler->appendSnapshot(runControl);
}
void DebuggerPlugin::runControlFinished(DebuggerRunControl *runControl)
......@@ -2724,6 +2703,7 @@ bool DebuggerPlugin::isRegisterViewVisible() const
return d->m_registerDock->toggleViewAction()->isChecked();
}
//////////////////////////////////////////////////////////////////////
//
// Testing
......
......@@ -85,6 +85,7 @@ public:
static DebuggerRunControl *createDebugger(const DebuggerStartParameters &sp);
static void startDebugger(ProjectExplorer::RunControl *runControl);
static void displayDebugger(ProjectExplorer::RunControl *runControl);
QMessageBox *showMessageBox(int icon, const QString &title,
const QString &text, int buttons = 0);
......
......@@ -69,7 +69,6 @@ public:
virtual void interruptInferior() = 0;
virtual void shutdownInferior() = 0;
virtual void shutdownAdapter() = 0;
//virtual const char *inferiorShutdownCommand() const;
virtual AbstractGdbProcess *gdbProc() = 0;
virtual DumperHandling dumperHandling() const = 0;
......
......@@ -574,7 +574,8 @@ void GdbEngine::updateAllClassic()
{
PRECONDITION;
PENDING_DEBUG("UPDATING ALL\n");
QTC_ASSERT(state() == InferiorUnrunnable || state() == InferiorStopOk, /**/);
QTC_ASSERT(state() == InferiorUnrunnable || state() == InferiorStopOk,
qDebug() << state());
tryLoadDebuggingHelpersClassic();
reloadModulesInternal();
postCommand("-stack-list-frames", WatchUpdate,
......
......@@ -35,6 +35,7 @@
#include "debuggeruiswitcher.h"
#include "debuggermainwindow.h"
#include "debuggerplugin.h"
#include "debuggerrunner.h"
#include "attachgdbadapter.h"
#include "coregdbadapter.h"
......@@ -1831,7 +1832,7 @@ void GdbEngine::setupEngine()
unsigned GdbEngine::debuggerCapabilities() const
{
return ReverseSteppingCapability | SnapshotCapability
unsigned caps = ReverseSteppingCapability
| AutoDerefPointersCapability | DisassemblerCapability
| RegisterCapability | ShowMemoryCapability
| JumpToLineCapability | ReloadModuleCapability
......@@ -1840,6 +1841,11 @@ unsigned GdbEngine::debuggerCapabilities() const
| CreateFullBacktraceCapability
| WatchpointCapability
| AddWatcherCapability;
if (startParameters().startMode == AttachCore)
return caps;
return caps | SnapshotCapability;
}
void GdbEngine::continueInferiorInternal()
......@@ -2485,6 +2491,10 @@ void GdbEngine::attemptBreakpointSynchronization()
qDebug() << "SOURCES LIST CURRENTLY UPDATING"; return);
showMessage(_("ATTEMPT BREAKPOINT SYNC"));
// We don't have breakpoints in core files.
if (startParameters().startMode == AttachCore)
return;
switch (state()) {
case InferiorSetupRequested:
case InferiorRunRequested:
......@@ -3030,11 +3040,19 @@ void GdbEngine::makeSnapshot()
void GdbEngine::handleMakeSnapshot(const GdbResponse &response)
{
if (response.resultClass == GdbResultDone) {
SnapshotData snapshot;
snapshot.setDate(QDateTime::currentDateTime());
snapshot.setLocation(response.cookie.toString());
snapshot.setFrames(stackHandler()->frames());
snapshotHandler()->appendSnapshot(snapshot);
DebuggerStartParameters sp = startParameters();
sp.startMode = AttachCore;
sp.coreFile = response.cookie.toString();
//snapshot.setDate(QDateTime::currentDateTime());
StackFrames frames = stackHandler()->frames();
QString function = _("<unknown>");
if (!frames.isEmpty()) {
const StackFrame &frame = frames.at(0);
function = frame.function + _(":") + QString::number(frame.line);
}
sp.displayName = function + _(": ") + QDateTime::currentDateTime().toString();
DebuggerRunControl *rc = DebuggerPlugin::createDebugger(sp);
DebuggerPlugin::startDebugger(rc);
} else {
QByteArray msg = response.data.findChild("msg").data();
showMessageBox(QMessageBox::Critical, tr("Snapshot Creation Error"),
......@@ -3042,58 +3060,6 @@ void GdbEngine::handleMakeSnapshot(const GdbResponse &response)
}
}
void GdbEngine::activateSnapshot(int index)
{
SnapshotData snapshot = snapshotHandler()->setCurrentIndex(index);
DebuggerStartParameters &sp =
const_cast<DebuggerStartParameters &>(startParameters());
sp.startMode = AttachCore;
sp.coreFile = snapshot.location();
if (state() == InferiorUnrunnable) {
// All is well. We are looking at another core file.
#if 0
// FIXME AAA
setState(EngineShutdownRequested);
setState(DebuggerNotReady);
#endif
activateSnapshot2();
} else if (state() != DebuggerNotReady) {
QMessageBox *mb = showMessageBox(QMessageBox::Critical,
tr("Snapshot Reloading"),
tr("In order to load snapshots the debugged process needs "
"to be stopped. Continuation will not be possible afterwards.\n"
"Do you want to stop the debugged process and load the selected "
"snapshot?"), QMessageBox::Ok | QMessageBox::Cancel);
if (mb->exec() == QMessageBox::Cancel)
return;
showMessage(_("KILLING DEBUGGER AS REQUESTED BY USER"));
delete m_gdbAdapter;
m_gdbAdapter = createAdapter();
postCommand("kill", NeedsStop, CB(handleActivateSnapshot));
} else {
activateSnapshot2();
}
}
void GdbEngine::handleActivateSnapshot(const GdbResponse &response)
{
Q_UNUSED(response);
quitDebugger();
}
void GdbEngine::activateSnapshot2()
{
// Otherwise the stack data might be stale.
// See http://sourceware.org/bugzilla/show_bug.cgi?id=1124.
#if 0
setState(EngineSetupRequested);
postCommand("set stack-cache off");
handleAdapterStarted();
#endif
}
//////////////////////////////////////////////////////////////////////
//
......
......@@ -378,9 +378,6 @@ private: ////////// View & Data Stuff //////////
//
virtual void makeSnapshot();
void handleMakeSnapshot(const GdbResponse &response);
void handleActivateSnapshot(const GdbResponse &response);
void activateSnapshot(int index);
void activateSnapshot2();
//
// Register specific stuff
......
/**************************************************************************
**
** This file is part of Qt Creator
**
** Copyright (c) 2010 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 "sessionengine.h"
#include "snapshothandler.h"
#include "breakhandler.h"
#include "watchhandler.h"
namespace Debugger {
namespace Internal {
// This class contains data serving as a template for debugger engines
// started during a session.
SessionEngine::SessionEngine()
: DebuggerEngine(DebuggerStartParameters()),
m_snapshotHandler(new SnapshotHandler(this))
{
}
void SessionEngine::loadSessionData()
{
breakHandler()->loadSessionData();
watchHandler()->loadSessionData();
}
void SessionEngine::saveSessionData()
{
watchHandler()->saveSessionData();
breakHandler()->saveSessionData();
}
} // namespace Internal
} // namespace Debugger
/**************************************************************************
**
** This file is part of Qt Creator
**
** Copyright (c) 2010 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_SESSIONENGINE_H
#define DEBUGGER_SESSIONENGINE_H
#include "debuggerengine.h"
namespace Debugger {
namespace Internal {
class SnapshotHandler;
// This class contains data serving as a template for debugger engines
// started during a session.
class SessionEngine : public DebuggerEngine
{
public:
SessionEngine();
void setupEngine() {}
void setupInferior() {}
void runEngine() {}
void shutdownEngine() {}
void shutdownInferior() {}
bool isSessionEngine() const { return true; }
void loadSessionData();
void saveSessionData();
public:
// The global set of snapshots.
SnapshotHandler *m_snapshotHandler;
// The model serving as command dispatcher.
};
} // namespace Internal
} // namespace Debugger
#endif // DEBUGGER_SESSIONENGINE_H
......@@ -29,9 +29,12 @@
#include "snapshothandler.h"
#include "sessionengine.h"
#include "debuggeractions.h"
#include "debuggerconstants.h"
#include "debuggerengine.h"
#include "debuggerrunner.h"
#include "debuggerplugin.h"
#include <utils/qtcassert.h>
#include <utils/savedaction.h>
......@@ -44,6 +47,7 @@
namespace Debugger {
namespace Internal {
#if 0
SnapshotData::SnapshotData()
{}
......@@ -104,6 +108,7 @@ QDebug operator<<(QDebug d, const SnapshotData &f)
d.nospace() << res;
return d;
}
#endif
////////////////////////////////////////////////////////////////////////
//
......@@ -111,20 +116,25 @@ QDebug operator<<(QDebug d, const SnapshotData &f)
//
////////////////////////////////////////////////////////////////////////
SnapshotHandler::SnapshotHandler(DebuggerEngine *engine)
SnapshotHandler::SnapshotHandler(SessionEngine *engine)
: m_engine(engine),
m_positionIcon(QIcon(":/debugger/images/location_16.png")),
m_emptyIcon(QIcon(":/debugger/images/debugger_empty_14.png"))
{
m_currentIndex = 0;
connect(theDebuggerAction(OperateByInstruction), SIGNAL(triggered()),
this, SLOT(resetModel()));
m_currentIndex = -1;
}
SnapshotHandler::~SnapshotHandler()
{
foreach (const SnapshotData &snapshot, m_snapshots)
QFile::remove(snapshot.location());
for (int i = m_snapshots.size(); --i >= 0; ) {
QString file = engineAt(i)->startParameters().coreFile;
QFile::remove(file);
}