Commit 6a6cba55 authored by hjk's avatar hjk

debugger: The DebuggerEngine refactoring.

This replaces the (de facto) singleton engines and data handlers by classes
that are instantiated per run. The DebuggerRunControl will now create an
object of (a class derived from) DebuggerEngine that contains all the relevant
"dynamic" data.

DebuggerManager is no more. The "singleton" bits are merged into DebuggerPlugin,
whereas the data bits went to DebuggerEngine.

There is no formal notion of a "current" DebuggerEngine. However, as there's
only one DebuggerEngine at a time that has its data models connected to the
view, there's still some "de facto" notion of a "current" engine. Calling
SomeModel::setData(int role, QVariant data) with custom role is used as the
primary dispatch mechanism from the views to the "current" data models
(and the engine, as all data models know their engine).
parent 4cc24446
......@@ -942,7 +942,7 @@ class Dumper:
pass
except:
# Locals with failing memory access.
with SubItem(d):
with SubItem(self):
self.put('iname="%s",' % item.iname)
self.put('name="%s",' % item.name)
self.put('addr="<not accessible>",')
......@@ -963,7 +963,7 @@ class Dumper:
p += 1
n += 1
with SubItem(d):
with SubItem(self):
self.put('iname="%s",' % item.iname)
self.putName(item.name)
self.putItemCount(select(n <= 100, n, "> 100"))
......
This diff is collapsed.
......@@ -39,6 +39,8 @@
namespace Debugger {
namespace Internal {
class DebuggerEngine;
//////////////////////////////////////////////////////////////////
//
// BreakHandler
......@@ -50,7 +52,7 @@ class BreakHandler : public QAbstractTableModel
Q_OBJECT
public:
explicit BreakHandler(DebuggerManager *manager, QObject *parent = 0);
explicit BreakHandler(DebuggerEngine *engine);
~BreakHandler();
void removeAllBreakpoints();
......@@ -67,23 +69,25 @@ public:
void removeAt(int index); // This also deletes the marker.
void clear(); // This also deletes all the marker.
int indexOf(BreakpointData *data) { return m_bp.indexOf(data); }
// Find a breakpoint matching approximately the data in needle.bp*,
BreakpointData *findSimilarBreakpoint(const BreakpointData &needle) const;
// Find a breakpoint matching approximately the data in needle.
BreakpointData *findSimilarBreakpoint(const BreakpointData *needle) const;
BreakpointData *findBreakpointByNumber(int bpNumber) const;
int findWatchPointIndexByAddress(const QByteArray &a) const;
bool watchPointAt(quint64 address) const;
void updateMarkers();
QList<BreakpointData *> insertedBreakpoints() const;
Breakpoints insertedBreakpoints() const;
void takeInsertedBreakPoint(BreakpointData *);
QList<BreakpointData *> takeRemovedBreakpoints(); // Owned.
QList<BreakpointData *> takeEnabledBreakpoints(); // Not owned.
QList<BreakpointData *> takeDisabledBreakpoints(); // Not owned.
Breakpoints takeRemovedBreakpoints(); // Owned.
Breakpoints takeEnabledBreakpoints(); // Not owned.
Breakpoints takeDisabledBreakpoints(); // Not owned.
QIcon breakpointIcon() const { return m_breakpointIcon; }
QIcon disabledBreakpointIcon() const { return m_disabledBreakpointIcon; }
QIcon pendingBreakPointIcon() const { return m_pendingBreakPointIcon; }
void initializeFromTemplate(BreakHandler *other);
public slots:
void appendBreakpoint(BreakpointData *data);
void toggleBreakpointEnabled(BreakpointData *data);
......@@ -98,7 +102,7 @@ private:
int columnCount(const QModelIndex &parent) const;
int rowCount(const QModelIndex &parent) const;
QVariant data(const QModelIndex &index, int role) const;
bool setData(const QModelIndex &index, const QVariant &, int role);
bool setData(const QModelIndex &index, const QVariant &value, int role);
QVariant headerData(int section, Qt::Orientation orientation, int role) const;
Qt::ItemFlags flags(const QModelIndex &index) const;
......@@ -113,12 +117,16 @@ private:
const QIcon m_pendingBreakPointIcon;
const QIcon m_watchpointIcon;
DebuggerManager *m_manager; // Not owned.
QList<BreakpointData *> m_bp;
QList<BreakpointData *> m_inserted; // Lately inserted breakpoints.
QList<BreakpointData *> m_removed; // Lately removed breakpoints.
QList<BreakpointData *> m_enabled; // Lately enabled breakpoints.
QList<BreakpointData *> m_disabled; // Lately disabled breakpoints.
DebuggerEngine *m_engine; // Not owned.
Breakpoints m_bp;
Breakpoints m_inserted; // Lately inserted breakpoints.
Breakpoints m_removed; // Lately removed breakpoints.
Breakpoints m_enabled; // Lately enabled breakpoints.
Breakpoints m_disabled; // Lately disabled breakpoints.
// Hack for BreakWindow::findSimilarBreakpoint
mutable BreakpointData *m_lastFound;
mutable bool m_lastFoundQueried;
};
} // namespace Internal
......
......@@ -30,6 +30,8 @@
#ifndef DEBUGGER_BREAKPOINT_H
#define DEBUGGER_BREAKPOINT_H
#include <QtCore/QMetaType>
#include <QtCore/QList>
#include <QtCore/QString>
namespace Debugger {
......@@ -58,13 +60,17 @@ public:
BreakHandler *handler() { return m_handler; }
bool isLocatedAt(const QString &fileName, int lineNumber) const;
bool isSimilarTo(const BreakpointData *needle) const;
bool conditionsMatch() const;
protected:
// This copies only the static data.
BreakpointData(const BreakpointData &);
private:
// Intentionally unimplemented.
// Making it copyable is tricky because of the markers.
void operator=(const BreakpointData &);
BreakpointData(const BreakpointData &);
// Our owner
BreakHandler *m_handler; // Not owned.
......@@ -116,8 +122,11 @@ private:
BreakpointMarker *marker;
};
typedef QList<BreakpointData *> Breakpoints;
} // namespace Internal
} // namespace Debugger
Q_DECLARE_METATYPE(Debugger::Internal::BreakpointData *);
#endif // DEBUGGER_BREAKPOINT_H
This diff is collapsed.
/**************************************************************************
QT_END_NAMESPACE
**
** This file is part of Qt Creator
**
......@@ -31,12 +30,11 @@ QT_END_NAMESPACE
#ifndef DEBUGGER_BREAKWINDOW_H
#define DEBUGGER_BREAKWINDOW_H
#include "breakpoint.h"
#include <QtGui/QTreeView>
namespace Debugger {
class DebuggerManager;
namespace Internal {
class BreakWindow : public QTreeView
......@@ -44,31 +42,30 @@ class BreakWindow : public QTreeView
Q_OBJECT
public:
explicit BreakWindow(DebuggerManager *manager);
explicit BreakWindow(QWidget *parent = 0);
~BreakWindow();
BreakpointData *findSimilarBreakpoint(const BreakpointData *needle);
void updateBreakpoint(BreakpointData *data);
void appendBreakpoint(BreakpointData *data);
void removeBreakpoint(BreakpointData *data);
QVariant modelData(int role, int index);
public slots:
void resizeColumnsToContents();
void setAlwaysResizeColumnsToContents(bool on);
signals:
void breakpointDeleted(int index);
void breakpointActivated(int index);
void breakpointSynchronizationRequested();
void breakByFunctionRequested(const QString &functionName);
void breakByFunctionMainRequested();
private slots:
void rowActivated(const QModelIndex &index);
void setAlternatingRowColorsHelper(bool on) { setAlternatingRowColors(on); }
void showAddressColumn(bool on);
protected:
private:
void resizeEvent(QResizeEvent *ev);
void contextMenuEvent(QContextMenuEvent *ev);
void keyPressEvent(QKeyEvent *ev);
void mouseDoubleClickEvent(QMouseEvent *ev);
private:
void deleteBreakpoints(const QModelIndexList &list);
void deleteBreakpoints(QList<int> rows);
void editBreakpoint(const QModelIndexList &list);
......@@ -76,11 +73,12 @@ private:
void setBreakpointsEnabled(const QModelIndexList &list, bool enabled);
void setBreakpointsFullPath(const QModelIndexList &list, bool fullpath);
DebuggerManager *m_manager;
void setModelData(int role, const QVariant &value = QVariant(),
const QModelIndex &index = QModelIndex());
bool m_alwaysResizeColumnsToContents;
};
} // namespace Internal
} // namespace Debugger
......
......@@ -47,6 +47,8 @@ namespace CdbCore {
* When/How many times it triggers can be influenced by
* condition/ignorecount and 'oneshot'-flag. */
// FIXME: Merge with/derive from Debugger::Internal::Breakpoint
struct BreakPoint
{
enum Type { Code, // Stop in code.
......
# Detect presence of "Debugging Tools For Windows"
# in case VS compilers are used.
# FIXME
CDB_PATH=""
false {
win32 {
contains(QMAKE_CXX, cl) {
......@@ -50,3 +54,5 @@ LIBS+=-lpsapi
} # exists($$CDB_PATH)
} # (QMAKE_CXX, cl)
} # win32
} # false
This diff is collapsed.
......@@ -30,14 +30,11 @@
#ifndef DEBUGGER_CDBENGINE_H
#define DEBUGGER_CDBENGINE_H
#include "idebuggerengine.h"
#include "debuggermanager.h"
#include "debuggerengine.h"
#include <QtCore/QSharedPointer>
namespace Debugger {
class DebuggerManager;
namespace Internal {
class DisassemblerViewAgent;
......@@ -46,19 +43,17 @@ class CdbDebugOutput;
class CdbDebugEnginePrivate;
struct CdbOptions;
class CdbDebugEngine : public IDebuggerEngine
class CdbDebugEngine : public DebuggerEngine
{
Q_DISABLE_COPY(CdbDebugEngine)
Q_OBJECT
explicit CdbDebugEngine(DebuggerManager *parent,
const QSharedPointer<CdbOptions> &options);
explicit CdbDebugEngine(const DebuggerStartParameters &sp);
public:
~CdbDebugEngine();
// Factory function that returns 0 if the debug engine library cannot be found.
static IDebuggerEngine *create(DebuggerManager *parent,
const QSharedPointer<CdbOptions> &options,
static DebuggerEngine *create(const DebuggerStartParameters &sp,
QString *errorMessage);
virtual void shutdown();
......
......@@ -31,18 +31,17 @@
#define DEBUGGER_CDBENGINEPRIVATE_H
#include "coreengine.h"
#include "debuggerconstants.h"
#include "cdboptions.h"
#include "cdbdumperhelper.h"
#include "stackhandler.h"
#include "debuggermanager.h"
#include <utils/consoleprocess.h>
#include <QtCore/QSharedPointer>
#include <QtCore/QMap>
namespace Debugger {
class DebuggerManager;
namespace Internal {
class WatchHandler;
......@@ -68,8 +67,7 @@ public:
StoppedOther
};
explicit CdbDebugEnginePrivate(const QSharedPointer<CdbOptions> &options,
CdbDebugEngine* engine);
explicit CdbDebugEnginePrivate(CdbDebugEngine* engine);
~CdbDebugEnginePrivate();
bool init(QString *errorMessage);
......@@ -128,7 +126,6 @@ public:
QSharedPointer<CdbDumperHelper> m_dumper;
CdbDebugEngine *m_engine;
inline DebuggerManager *manager() const;
CdbStackTraceContext *m_currentStackTrace;
EditorToolTipCache m_editorToolTipCache;
......
......@@ -31,7 +31,6 @@
#include "cdbdebugengine.h"
#include "cdbexceptionutils.h"
#include "cdbdebugengine_p.h"
#include "debuggermanager.h"
#include <QtCore/QDebug>
#include <QtCore/QTextStream>
......@@ -42,7 +41,7 @@ namespace Internal {
// ---------- CdbDebugEventCallback
CdbDebugEventCallback::CdbDebugEventCallback(CdbDebugEngine* dbg) :
CdbDebugEventCallback::CdbDebugEventCallback(CdbDebugEngine *dbg) :
m_pEngine(dbg)
{
}
......
......@@ -100,7 +100,7 @@ namespace Internal {
// the QtCored4.pdb file to be present as we need "qstrdup"
// as dummy symbol. This is ok ATM since dumpers only
// make sense for Qt apps.
static bool debuggeeLoadLibrary(CdbDebugEngine *manager,
static bool debuggeeLoadLibrary(CdbDebugEngine *cdbEngine,
CdbCore::CoreEngine *engine,
unsigned long threadId,
const QString &moduleName,
......@@ -109,7 +109,8 @@ static bool debuggeeLoadLibrary(CdbDebugEngine *manager,
if (loadDebug > 1)
qDebug() << Q_FUNC_INFO << moduleName;
// Try to ignore the breakpoints, skip stray startup-complete trap exceptions
QSharedPointer<CdbExceptionLoggerEventCallback> exLogger(new CdbExceptionLoggerEventCallback(LogWarning, true, manager));
QSharedPointer<CdbExceptionLoggerEventCallback>
exLogger(new CdbExceptionLoggerEventCallback(LogWarning, true, cdbEngine));
CdbCore::EventCallbackRedirector eventRedir(engine, exLogger);
Q_UNUSED(eventRedir)
// Make a call to LoadLibraryA. First, reserve memory in debugger
......@@ -251,7 +252,7 @@ bool CdbDumperInitThread::ensureDumperInitialized(CdbDumperHelper &h, QString *e
h.m_state = CdbDumperHelper::Disabled; // No message here
*errorMessage = QCoreApplication::translate("Debugger::Internal::CdbDumperHelper", "The custom dumper library could not be initialized: %1").arg(*errorMessage);
h.m_engine->showStatusMessage(*errorMessage, messageTimeOut);
h.m_engine->manager()->showQtDumperLibraryWarning(*errorMessage);
h.m_engine->showQtDumperLibraryWarning(*errorMessage);
}
if (loadDebug)
qDebug() << Q_FUNC_INFO << '\n' << thread.m_ok;
......
......@@ -42,9 +42,8 @@ namespace CdbCore {
}
namespace Debugger {
class DebuggerManager;
namespace Internal {
class CdbDumperInitThread;
class CdbDebugEngine;
......
......@@ -138,9 +138,10 @@ QString CdbOptionsPageWidget::searchKeywords() const
}
// ---------- CdbOptionsPage
CdbOptionsPage::CdbOptionsPage(const QSharedPointer<CdbOptions> &options) :
m_options(options)
CdbOptionsPage::CdbOptionsPage() :
m_options(new CdbOptions)
{
m_options->fromSettings(Core::ICore::instance()->settings());
}
CdbOptionsPage::~CdbOptionsPage()
......
......@@ -68,7 +68,7 @@ class CdbOptionsPage : public Core::IOptionsPage
Q_DISABLE_COPY(CdbOptionsPage)
Q_OBJECT
public:
explicit CdbOptionsPage(const QSharedPointer<CdbOptions> &options);
explicit CdbOptionsPage();
virtual ~CdbOptionsPage();
// IOptionsPage
......@@ -87,6 +87,7 @@ public:
// Load failure messages can be displayed here
void setFailureMessage(const QString &msg) { m_failureMessage = msg; }
QSharedPointer<CdbOptions> options() const { return m_options; }
signals:
void debuggerPathsChanged();
......
......@@ -28,10 +28,12 @@
**************************************************************************/
#include "cdbstacktracecontext.h"
#include "cdbsymbolgroupcontext.h"
#include "cdbdumperhelper.h"
#include "cdbdebugengine_p.h"
#include "debuggeractions.h"
#include "debuggerplugin.h"
#include "watchutils.h"
#include "threadshandler.h"
......@@ -61,18 +63,18 @@ CdbStackTraceContext *CdbStackTraceContext::create(const QSharedPointer<CdbDumpe
return ctx;
}
CdbCore::SymbolGroupContext
*CdbStackTraceContext::createSymbolGroup(const CdbCore::ComInterfaces & /* cif */,
int index,
const QString &prefix,
CIDebugSymbolGroup *comSymbolGroup,
QString *errorMessage)
CdbCore::SymbolGroupContext *
CdbStackTraceContext::createSymbolGroup(const CdbCore::ComInterfaces & /* cif */,
int index,
const QString &prefix,
CIDebugSymbolGroup *comSymbolGroup,
QString *errorMessage)
{
// Exclude uninitialized variables if desired
QStringList uninitializedVariables;
const CdbCore::StackFrame &frame = stackFrameAt(index);
if (theDebuggerAction(UseCodeModel)->isChecked())
getUninitializedVariables(DebuggerManager::instance()->cppCodeModelSnapshot(), frame.function, frame.fileName, frame.line, &uninitializedVariables);
getUninitializedVariables(DebuggerPlugin::instance()->cppCodeModelSnapshot(), frame.function, frame.fileName, frame.line, &uninitializedVariables);
if (debug)
qDebug() << frame << uninitializedVariables;
CdbSymbolGroupContext *sc = CdbSymbolGroupContext::create(prefix,
......@@ -113,7 +115,7 @@ QList<StackFrame> CdbStackTraceContext::stackFrames() const
}
bool CdbStackTraceContext::getThreads(const CdbCore::ComInterfaces &cif,
QList<ThreadData> *threads,
Threads *threads,
ULONG *currentThreadId,
QString *errorMessage)
{
......
......@@ -32,6 +32,7 @@
#include "stackhandler.h"
#include "stacktracecontext.h"
#include "threadshandler.h"
#include "cdbcom.h"
......@@ -74,7 +75,7 @@ public:
// get threads in stopped state
static bool getThreads(const CdbCore::ComInterfaces &cif,
QList<ThreadData> *threads,
Threads *threads,
ULONG *currentThreadId,
QString *errorMessage);
......
......@@ -21,14 +21,13 @@ HEADERS += breakhandler.h \
debuggeractions.h \
debuggerconstants.h \
debuggerdialogs.h \
debuggermanager.h \
debuggerengine.h \
debugger_global.h \
debuggeroutputwindow.h \
debuggerplugin.h \
debuggerrunner.h \
debuggertooltip.h \
debuggerstringutils.h \
idebuggerengine.h \
moduleshandler.h \
moduleswindow.h \
outputcollector.h \
......@@ -40,6 +39,7 @@ HEADERS += breakhandler.h \
stackwindow.h \
snapshothandler.h \
snapshotwindow.h \
sourcefileshandler.h \
sourcefileswindow.h \
threadswindow.h \
watchhandler.h \
......@@ -55,12 +55,11 @@ SOURCES += breakhandler.cpp \
debuggeragents.cpp \
debuggeractions.cpp \
debuggerdialogs.cpp \
debuggermanager.cpp \
debuggerengine.cpp \
debuggeroutputwindow.cpp \
debuggerplugin.cpp \
debuggerrunner.cpp \
debuggertooltip.cpp \
idebuggerengine.cpp \
moduleshandler.cpp \
moduleswindow.cpp \
outputcollector.cpp \
......@@ -71,6 +70,7 @@ SOURCES += breakhandler.cpp \
snapshotwindow.cpp \
stackhandler.cpp \
stackwindow.cpp \
sourcefileshandler.cpp \
sourcefileswindow.cpp \
threadswindow.cpp \
watchdata.cpp \
......
......@@ -64,7 +64,7 @@ namespace Internal {
//////////////////////////////////////////////////////////////////////////
DebuggerSettings::DebuggerSettings(QObject *parent)
: QObject(parent), m_gdbBinaryToolChainMap(new GdbBinaryToolChainMap)
: QObject(parent)
{}
DebuggerSettings::~DebuggerSettings()
......@@ -87,7 +87,7 @@ void DebuggerSettings::readSettings(QSettings *settings)
item->readSettings(settings);
// Convert gdb binaries from flat settings list (see writeSettings)
// into map ("binary1=gdb,1,2", "binary2=symbian_gdb,3,4").
m_gdbBinaryToolChainMap->clear();
m_gdbBinaryToolChainMap.clear();
const QChar separator = QLatin1Char(',');
const QString keyRoot = QLatin1String(gdbBinariesSettingsGroupC) + QLatin1Char('/') +
QLatin1String(debugModeGdbBinaryKeyC);
......@@ -102,15 +102,15 @@ void DebuggerSettings::readSettings(QSettings *settings)
const QString binary = tokens.front();
tokens.pop_front();
foreach(const QString &t, tokens)
m_gdbBinaryToolChainMap->insert(binary, t.toInt());
m_gdbBinaryToolChainMap.insert(binary, t.toInt());
}
// Linux defaults
#ifdef Q_OS_UNIX
if (m_gdbBinaryToolChainMap->isEmpty()) {
if (m_gdbBinaryToolChainMap.isEmpty()) {
const QString gdb = QLatin1String("gdb");
m_gdbBinaryToolChainMap->insert(gdb, ProjectExplorer::ToolChain::GCC);
m_gdbBinaryToolChainMap->insert(gdb, ProjectExplorer::ToolChain::OTHER);
m_gdbBinaryToolChainMap->insert(gdb, ProjectExplorer::ToolChain::UNKNOWN);
m_gdbBinaryToolChainMap.insert(gdb, ProjectExplorer::ToolChain::GCC);
m_gdbBinaryToolChainMap.insert(gdb, ProjectExplorer::ToolChain::OTHER);
m_gdbBinaryToolChainMap.insert(gdb, ProjectExplorer::ToolChain::UNKNOWN);
}
#endif
}
......@@ -124,8 +124,8 @@ void DebuggerSettings::writeSettings(QSettings *settings) const
QString lastBinary;
QStringList settingsList;
const QChar separator = QLatin1Char(',');
const GdbBinaryToolChainMap::const_iterator cend = m_gdbBinaryToolChainMap->constEnd();
for (GdbBinaryToolChainMap::const_iterator it = m_gdbBinaryToolChainMap->constBegin(); it != cend; ++it) {
const GdbBinaryToolChainMap::const_iterator cend = m_gdbBinaryToolChainMap.constEnd();
for (GdbBinaryToolChainMap::const_iterator it = m_gdbBinaryToolChainMap.constBegin(); it != cend; ++it) {
if (it.key() != lastBinary) {
lastBinary = it.key(); // Start new entry with first toolchain
settingsList.push_back(lastBinary);
......@@ -255,12 +255,6 @@ DebuggerSettings *DebuggerSettings::instance()
item->setTextPattern(tr("Watch Expression \"%1\" in Separate Window"));
instance->insertItem(WatchExpressionInWindow, item);
item = new SavedAction(instance);
instance->insertItem(AssignValue, item);
item = new SavedAction(instance);
instance->insertItem(AssignType, item);
item = new SavedAction(instance);
instance->insertItem(WatchPoint, item);
......
......@@ -32,7 +32,6 @@
#include <QtCore/QHash>
#include <QtCore/QMap>
#include <QtCore/QSharedPointer>
QT_BEGIN_NAMESPACE
class QAction;
......@@ -41,7 +40,7 @@ class QSettings;
QT_END_NAMESPACE
namespace Utils {
class SavedAction;
class SavedAction;
}
namespace Debugger {
......@@ -52,12 +51,14 @@ class DebuggerSettings : public QObject
Q_OBJECT
public:
typedef QMultiMap<QString, int> GdbBinaryToolChainMap;
typedef QSharedPointer<GdbBinaryToolChainMap> GdbBinaryToolChainMapPtr;
explicit DebuggerSettings(QObject *parent = 0);
~DebuggerSettings();
GdbBinaryToolChainMapPtr gdbBinaryToolChainMap() const { return m_gdbBinaryToolChainMap; }