aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/plugins/debugger/breakhandler.cpp20
-rw-r--r--src/plugins/debugger/breakhandler.h10
-rw-r--r--src/plugins/debugger/cdb/cdbdebugengine.cpp2
-rw-r--r--src/plugins/debugger/cpptools.cpp47
-rw-r--r--src/plugins/debugger/cpptools.h44
-rw-r--r--src/plugins/debugger/debuggeractions.cpp7
-rw-r--r--src/plugins/debugger/debuggeractions.h1
-rw-r--r--src/plugins/debugger/debuggeragents.cpp158
-rw-r--r--src/plugins/debugger/debuggeragents.h35
-rw-r--r--src/plugins/debugger/debuggerconstants.h2
-rw-r--r--src/plugins/debugger/debuggermanager.cpp98
-rw-r--r--src/plugins/debugger/debuggermanager.h17
-rw-r--r--src/plugins/debugger/debuggerplugin.cpp70
-rw-r--r--src/plugins/debugger/debuggerplugin.h10
-rw-r--r--src/plugins/debugger/debuggertooltip.h2
-rw-r--r--src/plugins/debugger/gdb/gdbengine.cpp195
-rw-r--r--src/plugins/debugger/gdb/gdbengine.h11
-rw-r--r--src/plugins/debugger/idebuggerengine.h8
-rw-r--r--src/plugins/debugger/registerhandler.cpp6
-rw-r--r--src/plugins/debugger/registerwindow.cpp19
-rw-r--r--src/plugins/debugger/registerwindow.h6
-rw-r--r--src/plugins/debugger/script/scriptengine.cpp5
-rw-r--r--src/plugins/debugger/stackframe.h60
-rw-r--r--src/plugins/debugger/stackhandler.cpp30
-rw-r--r--src/plugins/debugger/stackhandler.h18
-rw-r--r--src/plugins/debugger/stackwindow.cpp67
-rw-r--r--src/plugins/debugger/stackwindow.h7
-rw-r--r--src/plugins/debugger/watchwindow.cpp11
28 files changed, 757 insertions, 209 deletions
diff --git a/src/plugins/debugger/breakhandler.cpp b/src/plugins/debugger/breakhandler.cpp
index 7f333077c9d..ee6f75196d1 100644
--- a/src/plugins/debugger/breakhandler.cpp
+++ b/src/plugins/debugger/breakhandler.cpp
@@ -29,6 +29,9 @@
#include "breakhandler.h"
+#include "debuggermanager.h"
+#include "stackframe.h"
+
#include "imports.h" // TextEditor::BaseTextMark
#include <QtCore/QDebug>
@@ -242,8 +245,8 @@ bool BreakpointData::conditionsMatch() const
//
//////////////////////////////////////////////////////////////////
-BreakHandler::BreakHandler(QObject *parent)
- : QAbstractItemModel(parent)
+BreakHandler::BreakHandler(DebuggerManager *manager, QObject *parent)
+ : QAbstractItemModel(parent), m_manager(manager)
{
}
@@ -345,13 +348,12 @@ void BreakHandler::saveBreakpoints()
map.insert(QLatin1String("usefullpath"), QLatin1String("1"));
list.append(map);
}
- setSessionValueRequested("Breakpoints", list);
+ m_manager->setSessionValue("Breakpoints", list);
}
void BreakHandler::loadBreakpoints()
{
- QVariant value;
- sessionValueRequested("Breakpoints", &value);
+ QVariant value = m_manager->sessionValue("Breakpoints");
QList<QVariant> list = value.toList();
clear();
foreach (const QVariant &var, list) {
@@ -677,8 +679,12 @@ void BreakHandler::activateBreakpoint(int index)
{
const BreakpointData *data = at(index);
//qDebug() << "BREAKPOINT ACTIVATED: " << data->fileName;
- if (!data->markerFileName.isEmpty())
- emit gotoLocation(data->markerFileName, data->markerLineNumber, false);
+ if (!data->markerFileName.isEmpty()) {
+ StackFrame frame;
+ frame.file = data->markerFileName;
+ frame.line = data->markerLineNumber;
+ m_manager->gotoLocation(frame, false);
+ }
}
void BreakHandler::breakByFunction(const QString &functionName)
diff --git a/src/plugins/debugger/breakhandler.h b/src/plugins/debugger/breakhandler.h
index 77c96f20eee..d02800625ca 100644
--- a/src/plugins/debugger/breakhandler.h
+++ b/src/plugins/debugger/breakhandler.h
@@ -40,6 +40,7 @@ namespace Internal {
class BreakpointMarker;
class BreakHandler;
+class DebuggerManager;
//////////////////////////////////////////////////////////////////
//
@@ -113,7 +114,7 @@ class BreakHandler : public QAbstractItemModel
Q_OBJECT
public:
- explicit BreakHandler(QObject *parent = 0);
+ explicit BreakHandler(DebuggerManager *manager, QObject *parent = 0);
~BreakHandler();
void removeAllBreakpoints();
@@ -149,12 +150,6 @@ public slots:
void activateBreakpoint(int index);
void removeBreakpoint(int index);
-signals:
- void gotoLocation(const QString &fileName, int lineNumber, bool setMarker);
-
- void sessionValueRequested(const QString &name, QVariant *value);
- void setSessionValueRequested(const QString &name, const QVariant &value);
-
private:
friend class BreakpointMarker;
@@ -175,6 +170,7 @@ private:
void resetBreakpoints();
void removeBreakpointHelper(int index);
+ DebuggerManager *m_manager; // not owned
QList<BreakpointData *> m_bp;
QList<BreakpointData *> m_inserted; // lately inserted breakpoints
QList<BreakpointData *> m_removed; // lately removed breakpoints
diff --git a/src/plugins/debugger/cdb/cdbdebugengine.cpp b/src/plugins/debugger/cdb/cdbdebugengine.cpp
index c0732065937..51af8db4b70 100644
--- a/src/plugins/debugger/cdb/cdbdebugengine.cpp
+++ b/src/plugins/debugger/cdb/cdbdebugengine.cpp
@@ -1178,7 +1178,7 @@ void CdbDebugEngine::activateFrame(int frameIndex)
break;
}
- m_d->m_debuggerManager->gotoLocation(frame.file, frame.line, true);
+ m_d->m_debuggerManager->gotoLocation(frame, true);
if (oldIndex != frameIndex || m_d->m_firstActivatedFrame) {
watchHandler->beginCycle();
diff --git a/src/plugins/debugger/cpptools.cpp b/src/plugins/debugger/cpptools.cpp
new file mode 100644
index 00000000000..9b38e4615eb
--- /dev/null
+++ b/src/plugins/debugger/cpptools.cpp
@@ -0,0 +1,47 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation ([email protected])
+**
+** 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 "cpptools.h"
+
+namespace Debugger {
+namespace Internal {
+
+QByteArray mangleName(const QByteArray &ba)
+{
+ return ba;
+}
+
+
+QByteArray demangleName(const QByteArray &ba)
+{
+ return ba;
+}
+
+} // namespace Internal
+} // namespace Debugger
diff --git a/src/plugins/debugger/cpptools.h b/src/plugins/debugger/cpptools.h
new file mode 100644
index 00000000000..e056d07cd45
--- /dev/null
+++ b/src/plugins/debugger/cpptools.h
@@ -0,0 +1,44 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation ([email protected])
+**
+** 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_CPPTOOLS_H
+#define DEBUGGER_CPPTOOLS_H
+
+#include <QtCore/QByteArray>
+
+namespace Debugger {
+namespace Internal {
+
+QByteArray mangleName(const QByteArray &ba);
+QByteArray demangleName(const QByteArray &ba);
+
+} // namespace Internal
+} // namespace Debugger
+
+#endif // DEBUGGER_WATCHWINDOW_H
diff --git a/src/plugins/debugger/debuggeractions.cpp b/src/plugins/debugger/debuggeractions.cpp
index 6c8f60bcb15..6b86696c0a5 100644
--- a/src/plugins/debugger/debuggeractions.cpp
+++ b/src/plugins/debugger/debuggeractions.cpp
@@ -151,6 +151,13 @@ DebuggerSettings *DebuggerSettings::instance()
item->setDefaultValue(false);
instance->insertItem(LogTimeStamps, item);
+ item = new SavedAction(instance);
+ item->setText(tr("Step by instruction"));
+ item->setCheckable(true);
+ item->setDefaultValue(false);
+ item->setIcon(QIcon(":/debugger/images/debugger_stepoverproc_small.png"));
+ instance->insertItem(StepByInstruction, item);
+
//
// Locals & Watchers
//
diff --git a/src/plugins/debugger/debuggeractions.h b/src/plugins/debugger/debuggeractions.h
index a929d2e8ccf..6d9656ffce0 100644
--- a/src/plugins/debugger/debuggeractions.h
+++ b/src/plugins/debugger/debuggeractions.h
@@ -77,6 +77,7 @@ enum DebuggerActionCode
AutoQuit,
LockView,
LogTimeStamps,
+ StepByInstruction,
RecheckDebuggingHelpers,
UseDebuggingHelpers,
diff --git a/src/plugins/debugger/debuggeragents.cpp b/src/plugins/debugger/debuggeragents.cpp
index 3f6550f1d76..8e5e5bc1125 100644
--- a/src/plugins/debugger/debuggeragents.cpp
+++ b/src/plugins/debugger/debuggeragents.cpp
@@ -30,16 +30,60 @@
#include "debuggeragents.h"
#include "idebuggerengine.h"
+#include <coreplugin/coreconstants.h>
#include <coreplugin/editormanager/editormanager.h>
+#include <coreplugin/editormanager/ieditor.h>
+#include <coreplugin/icore.h>
+
+#include <texteditor/basetexteditor.h>
+#include <texteditor/basetextmark.h>
+#include <texteditor/itexteditor.h>
+#include <texteditor/texteditorconstants.h>
+
+#include <utils/qtcassert.h>
+
+#include <QtGui/QPlainTextEdit>
+#include <QtGui/QTextCursor>
#include <limits.h>
namespace Debugger {
namespace Internal {
+///////////////////////////////////////////////////////////////////////
+//
+// MemoryViewAgent
+//
+///////////////////////////////////////////////////////////////////////
+
+/*!
+ \class MemoryViewAgent
+
+ Objects form this class are created in response to user actions in
+ the Gui for showing raw memory from the inferior. After creation
+ it handles communication between the engine and the bineditor.
+*/
+
MemoryViewAgent::MemoryViewAgent(DebuggerManager *manager, quint64 addr)
: QObject(manager), m_engine(manager->currentEngine())
{
+ init(addr);
+}
+
+MemoryViewAgent::MemoryViewAgent(DebuggerManager *manager, const QString &addr)
+ : QObject(manager), m_engine(manager->currentEngine())
+{
+ bool ok = true;
+ init(addr.toUInt(&ok, 0));
+}
+
+MemoryViewAgent::~MemoryViewAgent()
+{
+ m_editor->deleteLater();
+}
+
+void MemoryViewAgent::init(quint64 addr)
+{
Core::EditorManager *editorManager = Core::EditorManager::instance();
QString titlePattern = "Memory $";
m_editor = editorManager->openEditorWithContents(
@@ -49,12 +93,7 @@ MemoryViewAgent::MemoryViewAgent(DebuggerManager *manager, quint64 addr)
this, SLOT(fetchLazyData(int,bool)));
editorManager->activateEditor(m_editor);
QMetaObject::invokeMethod(m_editor->widget(), "setLazyData",
- Q_ARG(int, addr), Q_ARG(int, INT_MAX), Q_ARG(int, BinBlockSize));
-}
-
-MemoryViewAgent::~MemoryViewAgent()
-{
- m_editor->deleteLater();
+ Q_ARG(int, addr), Q_ARG(int, INT_MAX), Q_ARG(int, BinBlockSize));
}
void MemoryViewAgent::fetchLazyData(int block, bool sync)
@@ -70,6 +109,113 @@ void MemoryViewAgent::addLazyData(quint64 addr, const QByteArray &ba)
}
+///////////////////////////////////////////////////////////////////////
+//
+// DisassemblerViewAgent
+//
+///////////////////////////////////////////////////////////////////////
+
+static QIcon locationMarkIcon()
+{
+ static const QIcon icon(":/debugger/images/location.svg");
+ return icon;
+}
+
+// Used for the disassembler view
+class LocationMark2 : public TextEditor::ITextMark
+{
+public:
+ LocationMark2() {}
+
+ QIcon icon() const { return locationMarkIcon(); }
+ void updateLineNumber(int /*lineNumber*/) {}
+ void updateBlock(const QTextBlock & /*block*/) {}
+ void removedFromEditor() {}
+ void documentClosing() {}
+};
+
+struct DisassemblerViewAgentPrivate
+{
+ QPointer<TextEditor::ITextEditor> editor;
+ QPointer<IDebuggerEngine> engine;
+ QString address;
+ LocationMark2 *locationMark;
+};
+
+/*!
+ \class DisassemblerViewAgent
+
+ Objects from this class are created in response to user actions in
+ the Gui for showing disassembled memory from the inferior. After creation
+ it handles communication between the engine and the editor.
+*/
+
+DisassemblerViewAgent::DisassemblerViewAgent(DebuggerManager *manager)
+ : QObject(manager), d(new DisassemblerViewAgentPrivate)
+{
+ d->editor = 0;
+ d->engine = manager->currentEngine();
+ d->locationMark = new LocationMark2();
+}
+
+DisassemblerViewAgent::~DisassemblerViewAgent()
+{
+ if (d->editor)
+ d->editor->deleteLater();
+ delete d;
+}
+
+void DisassemblerViewAgent::setFrame(const StackFrame &frame)
+{
+ d->engine->fetchDisassembler(this, frame);
+ d->address = frame.address;
+}
+
+void DisassemblerViewAgent::setContents(const QString &contents)
+{
+ using namespace Core;
+ using namespace TextEditor;
+
+ EditorManager *editorManager = EditorManager::instance();
+ if (!d->editor) {
+ QString titlePattern = "Disassembler";
+ d->editor = qobject_cast<ITextEditor *>(
+ editorManager->openEditorWithContents(
+ Core::Constants::K_DEFAULT_TEXT_EDITOR,
+ &titlePattern));
+ }
+
+ editorManager->activateEditor(d->editor);
+
+ QPlainTextEdit *plainTextEdit =
+ qobject_cast<QPlainTextEdit *>(d->editor->widget());
+ if (plainTextEdit)
+ plainTextEdit->setPlainText(contents);
+
+ d->editor->markableInterface()->removeMark(d->locationMark);
+
+ for (int pos = 0, line = 0; ; ++line, ++pos) {
+ if (contents.midRef(pos, d->address.size()) == d->address) {
+ d->editor->markableInterface()->addMark(d->locationMark, line + 1);
+ if (plainTextEdit) {
+ QTextCursor tc = plainTextEdit->textCursor();
+ tc.setPosition(pos);
+ plainTextEdit->setTextCursor(tc);
+ }
+ break;
+ }
+ pos = contents.indexOf('\n', pos + 1);
+ if (pos == -1)
+ break;
+ }
+}
+
+QString DisassemblerViewAgent::address() const
+{
+ return d->address;
+}
+
} // namespace Internal
} // namespace Debugger
+#include "debuggeragents.moc"
diff --git a/src/plugins/debugger/debuggeragents.h b/src/plugins/debugger/debuggeragents.h
index f9984b84933..b48eb703af6 100644
--- a/src/plugins/debugger/debuggeragents.h
+++ b/src/plugins/debugger/debuggeragents.h
@@ -31,26 +31,21 @@
#define DEBUGGER_AGENTS_H
#include "debuggermanager.h"
+#include "stackframe.h"
-#include <coreplugin/icore.h>
-#include <coreplugin/coreconstants.h>
#include <coreplugin/editormanager/ieditor.h>
-#include <utils/qtcassert.h>
-
#include <QtCore/QObject>
#include <QtCore/QDebug>
#include <QtCore/QPointer>
#include <QtGui/QAction>
+
namespace Debugger {
namespace Internal {
class DebuggerManager;
-
-// Object form this class are created in response to user actions in
-// the Gui for showing raw memory from the inferior. After creation
-// it handles communication between the engine and the bineditor.
+class DisassemblerViewAgentPrivate;
class MemoryViewAgent : public QObject
{
@@ -59,6 +54,7 @@ class MemoryViewAgent : public QObject
public:
// Called from Gui
MemoryViewAgent(DebuggerManager *manager, quint64 startaddr);
+ MemoryViewAgent(DebuggerManager *manager, const QString &startaddr);
~MemoryViewAgent();
enum { BinBlockSize = 1024 };
@@ -69,11 +65,32 @@ public slots:
// Called from Editor
void fetchLazyData(int block, bool sync);
-public:
+private:
+ void init(quint64 startaddr);
+
QPointer<IDebuggerEngine> m_engine;
QPointer<Core::IEditor> m_editor;
};
+
+class DisassemblerViewAgent : public QObject
+{
+ Q_OBJECT
+
+public:
+ // Called from Gui
+ DisassemblerViewAgent(DebuggerManager *manager);
+ ~DisassemblerViewAgent();
+
+ void setFrame(const StackFrame &frame);
+ Q_SLOT void setContents(const QString &contents);
+ QString address() const;
+
+private:
+ DisassemblerViewAgentPrivate *d;
+};
+
+
} // namespace Internal
} // namespace Debugger
diff --git a/src/plugins/debugger/debuggerconstants.h b/src/plugins/debugger/debuggerconstants.h
index 0ff77414952..337ab8ba342 100644
--- a/src/plugins/debugger/debuggerconstants.h
+++ b/src/plugins/debugger/debuggerconstants.h
@@ -45,8 +45,6 @@ const char * const RESET = "Debugger.Reset";
const char * const STEP = "Debugger.StepLine";
const char * const STEPOUT = "Debugger.StepOut";
const char * const NEXT = "Debugger.NextLine";
-const char * const STEPI = "Debugger.StepInstruction";
-const char * const NEXTI = "Debugger.NextInstruction";
const char * const REVERSE = "Debugger.ReverseDirection";
const char * const M_DEBUG_VIEWS = "Debugger.Menu.View.Debug";
diff --git a/src/plugins/debugger/debuggermanager.cpp b/src/plugins/debugger/debuggermanager.cpp
index 6d81c5ecdd0..76b253726be 100644
--- a/src/plugins/debugger/debuggermanager.cpp
+++ b/src/plugins/debugger/debuggermanager.cpp
@@ -219,8 +219,8 @@ void DebuggerManager::init()
m_disassemblerWindow = new DisassemblerWindow;
m_modulesWindow = new ModulesWindow(this);
m_outputWindow = new DebuggerOutputWindow;
- m_registerWindow = new RegisterWindow;
- m_stackWindow = new StackWindow;
+ m_registerWindow = new RegisterWindow(this);
+ m_stackWindow = new StackWindow(this);
m_sourceFilesWindow = new SourceFilesWindow;
m_threadsWindow = new ThreadsWindow;
m_localsWindow = new WatchWindow(WatchWindow::LocalsType, this);
@@ -261,7 +261,7 @@ void DebuggerManager::init()
this, SLOT(reloadDisassembler()));
// Breakpoints
- m_breakHandler = new BreakHandler;
+ m_breakHandler = new BreakHandler(this);
QAbstractItemView *breakView =
qobject_cast<QAbstractItemView *>(m_breakWindow);
breakView->setModel(m_breakHandler->model());
@@ -271,12 +271,6 @@ void DebuggerManager::init()
m_breakHandler, SLOT(removeBreakpoint(int)));
connect(breakView, SIGNAL(breakpointSynchronizationRequested()),
this, SLOT(attemptBreakpointSynchronization()));
- connect(m_breakHandler, SIGNAL(gotoLocation(QString,int,bool)),
- this, SLOT(gotoLocation(QString,int,bool)));
- connect(m_breakHandler, SIGNAL(sessionValueRequested(QString,QVariant*)),
- this, SIGNAL(sessionValueRequested(QString,QVariant*)));
- connect(m_breakHandler, SIGNAL(setSessionValueRequested(QString,QVariant)),
- this, SIGNAL(setSessionValueRequested(QString,QVariant)));
connect(breakView, SIGNAL(breakByFunctionRequested(QString)),
this, SLOT(breakByFunction(QString)), Qt::QueuedConnection);
connect(breakView, SIGNAL(breakByFunctionMainRequested()),
@@ -357,16 +351,6 @@ void DebuggerManager::init()
//m_stepAction->setShortcut(QKeySequence(tr("F7")));
m_stepAction->setIcon(QIcon(":/debugger/images/debugger_stepinto_small.png"));
- m_nextIAction = new QAction(this);
- m_nextIAction->setText(tr("Step Over Instruction"));
- //m_nextIAction->setShortcut(QKeySequence(tr("Shift+F6")));
- m_nextIAction->setIcon(QIcon(":/debugger/images/debugger_stepoverproc_small.png"));
-
- m_stepIAction = new QAction(this);
- m_stepIAction->setText(tr("Step One Instruction"));
- //m_stepIAction->setShortcut(QKeySequence(tr("Shift+F9")));
- m_stepIAction->setIcon(QIcon(":/debugger/images/debugger_steponeproc_small.png"));
-
m_stepOutAction = new QAction(this);
m_stepOutAction->setText(tr("Step Out"));
//m_stepOutAction->setShortcut(QKeySequence(tr("Shift+F7")));
@@ -405,10 +389,8 @@ void DebuggerManager::init()
this, SLOT(nextExec()));
connect(m_stepAction, SIGNAL(triggered()),
this, SLOT(stepExec()));
- connect(m_nextIAction, SIGNAL(triggered()),
- this, SLOT(nextIExec()));
- connect(m_stepIAction, SIGNAL(triggered()),
- this, SLOT(stepIExec()));
+ connect(theDebuggerAction(StepByInstruction), SIGNAL(triggered()),
+ this, SLOT(stepByInstructionTriggered()));
connect(m_stepOutAction, SIGNAL(triggered()),
this, SLOT(stepOutExec()));
connect(m_runToLineAction, SIGNAL(triggered()),
@@ -427,9 +409,14 @@ void DebuggerManager::init()
connect(theDebuggerAction(ExecuteCommand), SIGNAL(triggered()),
this, SLOT(executeDebuggerCommand()));
+
connect(theDebuggerAction(WatchPoint), SIGNAL(triggered()),
this, SLOT(watchPoint()));
+ connect(theDebuggerAction(StepByInstruction), SIGNAL(triggered()),
+ this, SLOT(stepByInstructionTriggered()));
+
+
m_breakDock = m_mainWindow->addDockForWidget(m_breakWindow);
m_disassemblerDock = m_mainWindow->addDockForWidget(m_disassemblerWindow);
@@ -725,14 +712,6 @@ void DebuggerManager::updateWatchData(const WatchData &data)
m_engine->updateWatchData(data);
}
-QVariant DebuggerManager::sessionValue(const QString &name)
-{
- // this is answered by the plugin
- QVariant value;
- emit sessionValueRequested(name, &value);
- return value;
-}
-
static inline QString msgEngineNotAvailable(const char *engine)
{
return DebuggerManager::tr("The application requires the debugger engine '%1', which is disabled.").arg(QLatin1String(engine));
@@ -986,7 +965,10 @@ void DebuggerManager::stepExec()
{
QTC_ASSERT(m_engine, return);
resetLocation();
- m_engine->stepExec();
+ if (theDebuggerBoolSetting(StepByInstruction))
+ m_engine->stepIExec();
+ else
+ m_engine->stepExec();
}
void DebuggerManager::stepOutExec()
@@ -1000,21 +982,10 @@ void DebuggerManager::nextExec()
{
QTC_ASSERT(m_engine, return);
resetLocation();
- m_engine->nextExec();
-}
-
-void DebuggerManager::stepIExec()
-{
- QTC_ASSERT(m_engine, return);
- resetLocation();
- m_engine->stepIExec();
-}
-
-void DebuggerManager::nextIExec()
-{
- QTC_ASSERT(m_engine, return);
- resetLocation();
- m_engine->nextIExec();
+ if (theDebuggerBoolSetting(StepByInstruction))
+ m_engine->nextIExec();
+ else
+ m_engine->nextExec();
}
void DebuggerManager::watchPoint()
@@ -1190,8 +1161,6 @@ void DebuggerManager::setStatus(int status)
m_runToFunctionAction->setEnabled(ready);
m_jumpToLineAction->setEnabled(ready);
m_nextAction->setEnabled(ready);
- m_stepIAction->setEnabled(ready);
- m_nextIAction->setEnabled(ready);
//showStatusMessage(QString("started: %1, running: %2").arg(started).arg(running));
emit statusChanged(m_status);
const bool notbusy = ready || status == DebuggerProcessNotReady;
@@ -1316,17 +1285,26 @@ void DebuggerManager::resetLocation()
emit resetLocationRequested();
}
-void DebuggerManager::gotoLocation(const QString &fileName, int line,
- bool setMarker)
+void DebuggerManager::gotoLocation(const StackFrame &frame, bool setMarker)
{
// connected to the plugin
- emit gotoLocationRequested(fileName, line, setMarker);
+ emit gotoLocationRequested(frame, setMarker);
}
void DebuggerManager::fileOpen(const QString &fileName)
{
// connected to the plugin
- emit gotoLocationRequested(fileName, 1, false);
+ StackFrame frame;
+ frame.file = fileName;
+ frame.line = -1;
+ emit gotoLocationRequested(frame, false);
+}
+
+void DebuggerManager::stepByInstructionTriggered()
+{
+ QTC_ASSERT(m_stackHandler, return);
+ StackFrame frame = m_stackHandler->currentFrame();
+ gotoLocation(frame, true);
}
@@ -1497,6 +1475,20 @@ bool DebuggerManager::isReverseDebugging() const
return m_reverseDirectionAction->isChecked();
}
+QVariant DebuggerManager::sessionValue(const QString &name)
+{
+ // this is answered by the plugin
+ QVariant value;
+ emit sessionValueRequested(name, &value);
+ return value;
+}
+
+void DebuggerManager::setSessionValue(const QString &name, const QVariant &value)
+{
+ emit setSessionValueRequested(name, value);
+}
+
+
//////////////////////////////////////////////////////////////////////
//
// Testing
diff --git a/src/plugins/debugger/debuggermanager.h b/src/plugins/debugger/debuggermanager.h
index 65aa96f8099..8bf7e2a3aef 100644
--- a/src/plugins/debugger/debuggermanager.h
+++ b/src/plugins/debugger/debuggermanager.h
@@ -77,6 +77,7 @@ class DisassemblerHandler;
class ModulesHandler;
class RegisterHandler;
class SourceFilesWindow;
+class StackFrame;
class StackHandler;
class Symbol;
class ThreadsHandler;
@@ -141,8 +142,9 @@ enum LogChannel
LogMisc
};
-struct DebuggerStartParameters
+class DebuggerStartParameters
{
+public:
DebuggerStartParameters();
void clear();
@@ -281,9 +283,8 @@ public slots:
void setBusyCursor(bool on);
void queryCurrentTextEditor(QString *fileName, int *lineNumber, QObject **ed);
- QVariant sessionValue(const QString &name);
- void gotoLocation(const QString &file, int line, bool setLocationMarker);
+ void gotoLocation(const StackFrame &frame, bool setLocationMarker);
void fileOpen(const QString &file);
void resetLocation();
@@ -302,8 +303,6 @@ public slots:
void stepExec();
void stepOutExec();
void nextExec();
- void stepIExec();
- void nextIExec();
void continueExec();
void detachDebugger();
@@ -313,6 +312,8 @@ public slots:
void sessionLoaded();
void aboutToUnloadSession();
void aboutToSaveSession();
+ QVariant sessionValue(const QString &name);
+ void setSessionValue(const QString &name, const QVariant &value);
void assignValueInDebugger();
void assignValueInDebugger(const QString &expr, const QString &value);
@@ -346,6 +347,7 @@ private slots:
void clearStatusMessage();
void attemptBreakpointSynchronization();
void reloadFullStack();
+ void stepByInstructionTriggered();
private:
//
@@ -404,7 +406,7 @@ signals:
void debugModeRequested();
void previousModeRequested();
void statusMessageRequested(const QString &msg, int timeout); // -1 for 'forever'
- void gotoLocationRequested(const QString &file, int line, bool setLocationMarker);
+ void gotoLocationRequested(const StackFrame &frame, bool setLocationMarker);
void resetLocationRequested();
void currentTextEditorRequested(QString *fileName, int *lineNumber, QObject **ob);
void sessionValueRequested(const QString &name, QVariant *value);
@@ -468,8 +470,7 @@ private:
QAction *m_watchAction;
QAction *m_breakAction;
QAction *m_sepAction;
- QAction *m_stepIAction;
- QAction *m_nextIAction;
+ //QActio *m_stepByInstructionAction;
QAction *m_reverseDirectionAction;
QWidget *m_breakWindow;
diff --git a/src/plugins/debugger/debuggerplugin.cpp b/src/plugins/debugger/debuggerplugin.cpp
index 93f660b21b5..475f566aff5 100644
--- a/src/plugins/debugger/debuggerplugin.cpp
+++ b/src/plugins/debugger/debuggerplugin.cpp
@@ -31,10 +31,12 @@
#include "breakhandler.h"
#include "debuggeractions.h"
+#include "debuggeragents.h"
#include "debuggerdialogs.h"
#include "debuggerconstants.h"
#include "debuggermanager.h"
#include "debuggerrunner.h"
+#include "stackframe.h"
#include "ui_commonoptionspage.h"
#include "ui_dumperoptionpage.h"
@@ -116,6 +118,7 @@ const char * const TOGGLE_BREAK = "Debugger.ToggleBreak";
const char * const BREAK_BY_FUNCTION = "Debugger.BreakByFunction";
const char * const BREAK_AT_MAIN = "Debugger.BreakAtMain";
const char * const ADD_TO_WATCH = "Debugger.AddToWatch";
+const char * const STEP_BY_INSTRUCTION = "Debugger.StepByInstruction";
#ifdef Q_WS_MAC
const char * const INTERRUPT_KEY = "Shift+F5";
@@ -123,8 +126,6 @@ const char * const RESET_KEY = "Ctrl+Shift+F5";
const char * const STEP_KEY = "F7";
const char * const STEPOUT_KEY = "Shift+F7";
const char * const NEXT_KEY = "F6";
-const char * const STEPI_KEY = "Shift+F9";
-const char * const NEXTI_KEY = "Shift+F6";
const char * const REVERSE_KEY = "";
const char * const RUN_TO_LINE_KEY = "Shift+F8";
const char * const RUN_TO_FUNCTION_KEY = "Ctrl+F6";
@@ -139,8 +140,6 @@ const char * const RESET_KEY = "Ctrl+Shift+F5";
const char * const STEP_KEY = "F11";
const char * const STEPOUT_KEY = "Shift+F11";
const char * const NEXT_KEY = "F10";
-const char * const STEPI_KEY = "";
-const char * const NEXTI_KEY = "";
const char * const REVERSE_KEY = "F12";
const char * const RUN_TO_LINE_KEY = "";
const char * const RUN_TO_FUNCTION_KEY = "";
@@ -218,6 +217,13 @@ DebugMode::~DebugMode()
namespace Debugger {
namespace Internal {
+static QIcon locationMarkIcon()
+{
+ static const QIcon icon(":/debugger/images/location.svg");
+ return icon;
+}
+
+// Used in "real" editors
class LocationMark : public TextEditor::BaseTextMark
{
Q_OBJECT
@@ -226,25 +232,13 @@ public:
LocationMark(const QString &fileName, int linenumber)
: BaseTextMark(fileName, linenumber)
{}
- ~LocationMark();
- QIcon icon() const;
+ QIcon icon() const { return locationMarkIcon(); }
void updateLineNumber(int /*lineNumber*/) {}
void updateBlock(const QTextBlock & /*block*/) {}
void removedFromEditor() {}
};
-LocationMark::~LocationMark()
-{
- //qDebug() << "LOCATIONMARK DESTRUCTOR";
-}
-
-QIcon LocationMark::icon() const
-{
- static const QIcon icon(":/debugger/images/location.svg");
- return icon;
-}
-
} // namespace Internal
} // namespace Debugger
@@ -422,6 +416,7 @@ DebuggerPlugin::DebuggerPlugin()
: m_manager(0),
m_debugMode(0),
m_locationMark(0),
+ m_disassemblerViewAgent(0),
m_gdbRunningContext(0),
m_cmdLineEnabledEngines(AllEngineTypes),
m_cmdLineAttachPid(0),
@@ -682,14 +677,8 @@ bool DebuggerPlugin::initialize(const QStringList &arguments, QString *errorMess
cmd->setDefaultKeySequence(QKeySequence(Constants::STEPOUT_KEY));
mdebug->addAction(cmd);
- cmd = am->registerAction(m_manager->m_nextIAction,
- Constants::NEXTI, debuggercontext);
- cmd->setDefaultKeySequence(QKeySequence(Constants::NEXTI_KEY));
- mdebug->addAction(cmd);
-
- cmd = am->registerAction(m_manager->m_stepIAction,
- Constants::STEPI, debuggercontext);
- cmd->setDefaultKeySequence(QKeySequence(Constants::STEPI_KEY));
+ cmd = am->registerAction(theDebuggerAction(StepByInstruction),
+ Constants::STEP_BY_INSTRUCTION, debuggercontext);
mdebug->addAction(cmd);
cmd = am->registerAction(m_manager->m_runToLineAction,
@@ -831,9 +820,7 @@ bool DebuggerPlugin::initialize(const QStringList &arguments, QString *errorMess
debugToolBarLayout->addWidget(toolButton(am->command(Constants::NEXT)->action()));
debugToolBarLayout->addWidget(toolButton(am->command(Constants::STEP)->action()));
debugToolBarLayout->addWidget(toolButton(am->command(Constants::STEPOUT)->action()));
- debugToolBarLayout->addWidget(new Core::Utils::StyledSeparator);
- debugToolBarLayout->addWidget(toolButton(am->command(Constants::STEPI)->action()));
- debugToolBarLayout->addWidget(toolButton(am->command(Constants::NEXTI)->action()));
+ debugToolBarLayout->addWidget(toolButton(am->command(Constants::STEP_BY_INSTRUCTION)->action()));
#ifdef USE_REVERSE_DEBUGGING
debugToolBarLayout->addWidget(new Core::Utils::StyledSeparator);
debugToolBarLayout->addWidget(toolButton(am->command(Constants::REVERSE)->action()));
@@ -892,8 +879,8 @@ bool DebuggerPlugin::initialize(const QStringList &arguments, QString *errorMess
connect(m_manager, SIGNAL(resetLocationRequested()),
this, SLOT(resetLocation()));
- connect(m_manager, SIGNAL(gotoLocationRequested(QString,int,bool)),
- this, SLOT(gotoLocation(QString,int,bool)));
+ connect(m_manager, SIGNAL(gotoLocationRequested(StackFrame,bool)),
+ this, SLOT(gotoLocation(StackFrame,bool)));
connect(m_manager, SIGNAL(statusChanged(int)),
this, SLOT(changeStatus(int)));
connect(m_manager, SIGNAL(previousModeRequested()),
@@ -1096,17 +1083,23 @@ void DebuggerPlugin::resetLocation()
m_locationMark = 0;
}
-void DebuggerPlugin::gotoLocation(const QString &fileName, int lineNumber,
- bool setMarker)
+void DebuggerPlugin::gotoLocation(const StackFrame &frame, bool setMarker)
{
- TextEditor::BaseTextEditor::openEditorAt(fileName, lineNumber);
- if (setMarker) {
- resetLocation();
- m_locationMark = new LocationMark(fileName, lineNumber);
+ if (theDebuggerBoolSetting(StepByInstruction) || !frame.isUsable()) {
+ if (!m_disassemblerViewAgent)
+ m_disassemblerViewAgent = new DisassemblerViewAgent(m_manager);
+ m_disassemblerViewAgent->setFrame(frame);
+ if (setMarker)
+ resetLocation();
+ } else {
+ TextEditor::BaseTextEditor::openEditorAt(frame.file, frame.line);
+ if (setMarker) {
+ resetLocation();
+ m_locationMark = new LocationMark(frame.file, frame.line);
+ }
}
}
-
void DebuggerPlugin::changeStatus(int status)
{
bool startIsContinue = (status == DebuggerInferiorStopped);
@@ -1157,9 +1150,8 @@ void DebuggerPlugin::onModeChanged(IMode *mode)
// different then the debugger mode. E.g. Welcome and Help mode and
// also on shutdown.
- if (mode != m_debugMode) {
+ if (mode != m_debugMode)
return;
- }
EditorManager *editorManager = EditorManager::instance();
if (editorManager->currentEditor())
diff --git a/src/plugins/debugger/debuggerplugin.h b/src/plugins/debugger/debuggerplugin.h
index 01fe816d324..74928abe447 100644
--- a/src/plugins/debugger/debuggerplugin.h
+++ b/src/plugins/debugger/debuggerplugin.h
@@ -50,6 +50,8 @@ class IMode;
namespace TextEditor {
class ITextEditor;
+class ITextMark;
+class BaseTextMark;
}
namespace Debugger {
@@ -59,7 +61,8 @@ class BreakpointData;
class DebuggerManager;
class DebuggerRunner;
class DebugMode;
-class LocationMark;
+class DisassemblerViewAgent;
+class StackFrame;
class DebuggerPlugin : public ExtensionSystem::IPlugin
{
@@ -94,7 +97,7 @@ private slots:
void updateActions(int status);
void resetLocation();
- void gotoLocation(const QString &fileName, int line, bool setMarker);
+ void gotoLocation(const StackFrame &frame, bool setMarker);
void breakpointSetRemoveMarginActionTriggered();
void breakpointEnableDisableMarginActionTriggered();
@@ -127,7 +130,8 @@ private:
DebuggerRunner *m_debuggerRunner;
QString m_previousMode;
- LocationMark *m_locationMark;
+ TextEditor::BaseTextMark *m_locationMark;
+ DisassemblerViewAgent *m_disassemblerViewAgent;
int m_gdbRunningContext;
unsigned m_cmdLineEnabledEngines;
quint64 m_cmdLineAttachPid;
diff --git a/src/plugins/debugger/debuggertooltip.h b/src/plugins/debugger/debuggertooltip.h
index 59ff8807745..c543923381f 100644
--- a/src/plugins/debugger/debuggertooltip.h
+++ b/src/plugins/debugger/debuggertooltip.h
@@ -30,7 +30,7 @@
#ifndef DEBUGGER_DEBUGGERTOOLTIP_H
#define DEBUGGER_DEBUGGERTOOLTIP_H
-#include <qglobal.h>
+#include <QtCore/QtGlobal>
QT_BEGIN_NAMESPACE
class QAbstractItemModel;
diff --git a/src/plugins/debugger/gdb/gdbengine.cpp b/src/plugins/debugger/gdb/gdbengine.cpp
index 567f4e24dc5..74e8f6d13c9 100644
--- a/src/plugins/debugger/gdb/gdbengine.cpp
+++ b/src/plugins/debugger/gdb/gdbengine.cpp
@@ -970,11 +970,11 @@ void GdbEngine::handleExecRunToFunction(const GdbResultRecord &record, const QVa
qq->notifyInferiorStopped();
q->showStatusMessage(tr("Run to Function finished. Stopped."));
GdbMi frame = record.data.findChild("frame");
- QString file = QString::fromLocal8Bit(frame.findChild("fullname").data());
- int line = frame.findChild("line").data().toInt();
- qDebug() << "HIT:" << file << line << "IN" << frame.toString()
- << "--" << record.toString();
- q->gotoLocation(file, line, true);
+ StackFrame f;
+ f.file = QString::fromLocal8Bit(frame.findChild("fullname").data());
+ f.line = frame.findChild("line").data().toInt();
+ f.address = _(frame.findChild("addr").data());
+ q->gotoLocation(f, true);
}
static bool isExitedReason(const QByteArray &reason)
@@ -1229,11 +1229,11 @@ void GdbEngine::handleAsyncOutput(const GdbMi &data)
qq->notifyInferiorStopped();
q->showStatusMessage(tr("Run to Function finished. Stopped."));
GdbMi frame = data.findChild("frame");
- QString file = QString::fromLocal8Bit(frame.findChild("fullname").data());
- int line = frame.findChild("line").data().toInt();
- qDebug() << "HIT:" << file << line << "IN" << frame.toString()
- << "--" << data.toString();
- q->gotoLocation(file, line, true);
+ StackFrame f;
+ f.file = QString::fromLocal8Bit(frame.findChild("fullname").data());
+ f.line = frame.findChild("line").data().toInt();
+ f.address = _(frame.findChild("addr").data());
+ q->gotoLocation(f, true);
#endif
}
@@ -1853,6 +1853,9 @@ void GdbEngine::runToFunctionExec(const QString &functionName)
void GdbEngine::jumpToLineExec(const QString &fileName, int lineNumber)
{
+ StackFrame frame;
+ frame.file = fileName;
+ frame.line = lineNumber;
#if 1
// not available everywhere?
//sendCliCommand(_("tbreak ") + fileName + ':' + QString::number(lineNumber));
@@ -1864,11 +1867,11 @@ void GdbEngine::jumpToLineExec(const QString &fileName, int lineNumber)
// ~"run1 (argc=1, argv=0x7fffbf1f5538) at test1.cpp:242"
// ~"242\t x *= 2;"
// 23^done"
- q->gotoLocation(fileName, lineNumber, true);
+ q->gotoLocation(frame, true);
//setBreakpoint();
//postCommand(_("jump ") + fileName + ':' + QString::number(lineNumber));
#else
- q->gotoLocation(fileName, lineNumber, true);
+ q->gotoLocation(frame, true);
setBreakpoint(fileName, lineNumber);
postCommand(_("jump ") + fileName + ':' + QString::number(lineNumber));
#endif
@@ -2566,13 +2569,9 @@ void GdbEngine::handleStackListFrames(const GdbResultRecord &record, const QVari
theDebuggerAction(ExpandStack)->setEnabled(canExpand);
qq->stackHandler()->setFrames(stackFrames, canExpand);
- if (topFrame != -1) {
- // updates of locals already triggered early
+ if (topFrame != -1 || theDebuggerBoolSetting(StepByInstruction)) {
const StackFrame &frame = qq->stackHandler()->currentFrame();
- if (frame.isUsable())
- q->gotoLocation(frame.file, frame.line, true);
- else
- qDebug() << "FULL NAME NOT USABLE 0:" << frame.file << topFrame;
+ q->gotoLocation(frame, true);
}
}
@@ -2622,7 +2621,7 @@ void GdbEngine::activateFrame(int frameIndex)
const StackFrame &frame = stackHandler->currentFrame();
if (frame.isUsable())
- q->gotoLocation(frame.file, frame.line, true);
+ q->gotoLocation(frame, true);
else
qDebug() << "FULL NAME NOT USABLE:" << frame.file;
}
@@ -4004,6 +4003,18 @@ void GdbEngine::handleWatchPoint(const GdbResultRecord &record, const QVariant &
}
}
+static QVariant agentCookie(void *agent)
+{
+ return QVariant(quint64(quintptr(agent)));
+}
+
+void GdbEngine::fetchMemory(MemoryViewAgent *agent, quint64 addr, quint64 length)
+{
+ //qDebug() << "GDB MEMORY FETCH" << addr << length;
+ postCommand(_("-data-read-memory %1 x 1 1 %2").arg(addr).arg(length),
+ NeedsStop, CB(handleFetchMemory), agentCookie(agent));
+}
+
void GdbEngine::handleFetchMemory(const GdbResultRecord &record,
const QVariant &cookie)
{
@@ -4017,7 +4028,7 @@ void GdbEngine::handleFetchMemory(const GdbResultRecord &record,
QTC_ASSERT(agent, return);
QByteArray ba;
GdbMi memory = record.data.findChild("memory");
- QTC_ASSERT(memory.children().size() == 1, return);
+ QTC_ASSERT(memory.children().size() <= 1, return);
GdbMi memory0 = memory.children().at(0); // we asked for only one 'row'
quint64 addr = memory0.findChild("addr").data().toULongLong(&ok, 0);
QTC_ASSERT(ok, return);
@@ -4031,13 +4042,149 @@ void GdbEngine::handleFetchMemory(const GdbResultRecord &record,
agent->addLazyData(addr, ba);
}
-void GdbEngine::fetchMemory(MemoryViewAgent *agent, quint64 addr, quint64 length)
+
+void GdbEngine::fetchDisassembler(DisassemblerViewAgent *agent,
+ const StackFrame &frame)
{
- //qDebug() << "GDB MEMORY FETCH" << addr << length;
- postCommand(_("-data-read-memory %1 x 1 1 %2").arg(addr).arg(length),
- NeedsStop, CB(handleFetchMemory), QVariant(quint64(agent)));
+ if (frame.file.isEmpty()) {
+ fetchDisassemblerByAddress(agent, true);
+ } else {
+ // Disassemble full function:
+ QString cmd = _("-data-disassemble -f %1 -l %2 -n -1 -- 1");
+ postCommand(cmd.arg(frame.file).arg(frame.line),
+ Discardable, CB(handleFetchDisassemblerByLine), agentCookie(agent));
+ }
+}
+
+void GdbEngine::fetchDisassemblerByAddress(DisassemblerViewAgent *agent,
+ bool useMixedMode)
+{
+ QTC_ASSERT(agent, return);
+ bool ok = true;
+ quint64 address = agent->address().toULongLong(&ok, 0);
+ quint64 start = address - 20;
+ quint64 end = address + 100;
+ // -data-disassemble [ -s start-addr -e end-addr ]
+ // | [ -f filename -l linenum [ -n lines ] ] -- mode
+ if (useMixedMode)
+ postCommand(_("-data-disassemble -s %1 -e %2 -- 1").arg(start).arg(end),
+ Discardable, CB(handleFetchDisassemblerByAddress1), agentCookie(agent));
+ else
+ postCommand(_("-data-disassemble -s %1 -e %2 -- 0").arg(start).arg(end),
+ Discardable, CB(handleFetchDisassemblerByAddress0), agentCookie(agent));
+}
+
+static QByteArray parseLine(const GdbMi &line)
+{
+ QByteArray ba;
+ ba.reserve(200);
+ QByteArray address = line.findChild("address").data();
+ QByteArray funcName = line.findChild("func-name").data();
+ QByteArray offset = line.findChild("offset").data();
+ QByteArray inst = line.findChild("inst").data();
+ ba += address + QByteArray(15 - address.size(), ' ');
+ ba += funcName + "+" + offset + " ";
+ ba += QByteArray(30 - funcName.size() - offset.size(), ' ');
+ ba += inst;
+ ba += '\n';
+ return ba;
+}
+
+static QString parseDisassembler(const GdbMi &lines)
+{
+ // ^done,data={asm_insns=[src_and_asm_line={line="1243",file=".../app.cpp",
+ // line_asm_insn=[{address="0x08054857",func-name="main",offset="27",
+ // inst="call 0x80545b0 <_Z13testQFileInfov>"}]},
+ // src_and_asm_line={line="1244",file=".../app.cpp",
+ // line_asm_insn=[{address="0x0805485c",func-name="main",offset="32",
+ //inst="call 0x804cba1 <_Z11testObject1v>"}]}]}
+ // - or -
+ // ^done,asm_insns=[
+ // {address="0x0805acf8",func-name="...",offset="25",inst="and $0xe8,%al"},
+ // {address="0x0805acfa",func-name="...",offset="27",inst="pop %esp"},
+
+ QList<QByteArray> fileContents;
+ bool fileLoaded = false;
+ QByteArray ba;
+ ba.reserve(200 * lines.children().size());
+
+ // FIXME: Performance?
+ foreach (const GdbMi &child, lines.children()) {
+ if (child.hasName("src_and_asm_line")) {
+ // mixed mode
+ int line = child.findChild("line").data().toInt();
+ QByteArray fileName = child.findChild("file").data();
+ if (!fileLoaded) {
+ QFile file(QFile::decodeName(fileName));
+ file.open(QIODevice::ReadOnly);
+ fileContents = file.readAll().split('\n');
+ fileLoaded = true;
+ }
+ if (line >= 0 && line < fileContents.size())
+ ba += " " + fileContents.at(line) + '\n';
+
+ GdbMi insn = child.findChild("line_asm_insn");
+ foreach (const GdbMi &line, insn.children())
+ ba += parseLine(line);
+ } else {
+ // the non-mixed version
+ ba += parseLine(child);
+ }
+ }
+ return _(ba);
}
+void GdbEngine::handleFetchDisassemblerByLine(const GdbResultRecord &record,
+ const QVariant &cookie)
+{
+ bool ok = true;
+ DisassemblerViewAgent *agent = (DisassemblerViewAgent *)cookie.toULongLong(&ok);
+ QTC_ASSERT(agent, return);
+
+ if (record.resultClass == GdbResultDone) {
+ GdbMi lines = record.data.findChild("asm_insns");
+ if (lines.children().isEmpty())
+ fetchDisassemblerByAddress(agent, true);
+ else
+ agent->setContents(parseDisassembler(lines));
+ } else if (record.resultClass == GdbResultError) {
+ //536^error,msg="mi_cmd_disassemble: Invalid line number"
+ QByteArray msg = record.data.findChild("msg").data();
+ if (msg == "mi_cmd_disassemble: Invalid line number")
+ fetchDisassemblerByAddress(agent, true);
+ }
+}
+
+void GdbEngine::handleFetchDisassemblerByAddress1(const GdbResultRecord &record,
+ const QVariant &cookie)
+{
+ bool ok = true;
+ DisassemblerViewAgent *agent = (DisassemblerViewAgent *)cookie.toULongLong(&ok);
+ QTC_ASSERT(agent, return);
+
+ if (record.resultClass == GdbResultDone) {
+ GdbMi lines = record.data.findChild("asm_insns");
+ if (lines.children().isEmpty())
+ fetchDisassemblerByAddress(agent, false);
+ else
+ agent->setContents(parseDisassembler(lines));
+ }
+}
+
+void GdbEngine::handleFetchDisassemblerByAddress0(const GdbResultRecord &record,
+ const QVariant &cookie)
+{
+ bool ok = true;
+ DisassemblerViewAgent *agent = (DisassemblerViewAgent *)cookie.toULongLong(&ok);
+ QTC_ASSERT(agent, return);
+
+ if (record.resultClass == GdbResultDone) {
+ GdbMi lines = record.data.findChild("asm_insns");
+ agent->setContents(parseDisassembler(lines));
+ }
+}
+
+
IDebuggerEngine *createGdbEngine(DebuggerManager *parent, QList<Core::IOptionsPage*> *opts)
{
opts->push_back(new GdbOptionsPage);
diff --git a/src/plugins/debugger/gdb/gdbengine.h b/src/plugins/debugger/gdb/gdbengine.h
index 367b94856ce..3f16bd3701c 100644
--- a/src/plugins/debugger/gdb/gdbengine.h
+++ b/src/plugins/debugger/gdb/gdbengine.h
@@ -125,6 +125,17 @@ private:
void fetchMemory(MemoryViewAgent *agent, quint64 addr, quint64 length);
void handleFetchMemory(const GdbResultRecord &record, const QVariant &cookie);
+ void fetchDisassembler(DisassemblerViewAgent *agent,
+ const StackFrame &frame);
+ void fetchDisassemblerByAddress(DisassemblerViewAgent *agent,
+ bool useMixedMode);
+ void handleFetchDisassemblerByLine(const GdbResultRecord &record,
+ const QVariant &cookie);
+ void handleFetchDisassemblerByAddress1(const GdbResultRecord &record,
+ const QVariant &cookie);
+ void handleFetchDisassemblerByAddress0(const GdbResultRecord &record,
+ const QVariant &cookie);
+
Q_SLOT void setDebugDebuggingHelpers(const QVariant &on);
Q_SLOT void setUseDebuggingHelpers(const QVariant &on);
diff --git a/src/plugins/debugger/idebuggerengine.h b/src/plugins/debugger/idebuggerengine.h
index ad16fcec701..16b6d5ace5a 100644
--- a/src/plugins/debugger/idebuggerengine.h
+++ b/src/plugins/debugger/idebuggerengine.h
@@ -46,10 +46,12 @@ class ITextEditor;
namespace Debugger {
namespace Internal {
+class DebuggerStartParameters;
+class DisassemblerViewAgent;
+class MemoryViewAgent;
+class StackFrame;
class Symbol;
class WatchData;
-struct DebuggerStartParameters;
-class MemoryViewAgent;
class IDebuggerEngine : public QObject
{
@@ -98,6 +100,8 @@ public:
virtual void watchPoint(const QPoint &) {}
virtual void fetchMemory(MemoryViewAgent *, quint64 addr, quint64 length)
{ Q_UNUSED(addr); Q_UNUSED(length); }
+ virtual void fetchDisassembler(DisassemblerViewAgent *, const StackFrame &frame)
+ { Q_UNUSED(frame); }
};
} // namespace Internal
diff --git a/src/plugins/debugger/registerhandler.cpp b/src/plugins/debugger/registerhandler.cpp
index 8639261b594..a4cd71d394f 100644
--- a/src/plugins/debugger/registerhandler.cpp
+++ b/src/plugins/debugger/registerhandler.cpp
@@ -76,6 +76,12 @@ QVariant RegisterHandler::data(const QModelIndex &index, int role) const
const Register &reg = m_registers.at(index.row());
+ if (role == Qt::UserRole + 1) {
+ bool ok = true;
+ qulonglong value = reg.value.toULongLong(&ok, 0);
+ return QString::fromLatin1("0x") + QString::number(value, 16);
+ }
+
const QString padding = " ";
if (role == Qt::DisplayRole) {
switch (index.column()) {
diff --git a/src/plugins/debugger/registerwindow.cpp b/src/plugins/debugger/registerwindow.cpp
index 11a0340b6fa..2a8fd344373 100644
--- a/src/plugins/debugger/registerwindow.cpp
+++ b/src/plugins/debugger/registerwindow.cpp
@@ -30,6 +30,7 @@
#include "registerwindow.h"
#include "debuggeractions.h"
+#include "debuggeragents.h"
#include "debuggerconstants.h"
#include <QtCore/QDebug>
@@ -47,8 +48,9 @@
using namespace Debugger::Internal;
using namespace Debugger::Constants;
-RegisterWindow::RegisterWindow()
- : m_alwaysResizeColumnsToContents(true), m_alwaysReloadContents(false)
+RegisterWindow::RegisterWindow(DebuggerManager *manager)
+ : m_manager(manager), m_alwaysResizeColumnsToContents(true),
+ m_alwaysReloadContents(false)
{
QAction *act = theDebuggerAction(UseAlternatingRowColors);
setWindowTitle(tr("Registers"));
@@ -81,6 +83,17 @@ void RegisterWindow::contextMenuEvent(QContextMenuEvent *ev)
actAlwaysReload->setChecked(m_alwaysReloadContents);
menu.addSeparator();
+ QModelIndex idx = indexAt(ev->pos());
+ QString address = model()->data(idx, Qt::UserRole + 1).toString();
+ QAction *actShowMemory = menu.addAction(QString());
+ if (address.isEmpty()) {
+ actShowMemory->setText(tr("Open memory editor"));
+ actShowMemory->setEnabled(false);
+ } else {
+ actShowMemory->setText(tr("Open memory editor at %1").arg(address));
+ }
+ menu.addSeparator();
+
int base = model()->data(QModelIndex(), Qt::UserRole).toInt();
QAction *act16 = menu.addAction(tr("Hexadecimal"));
act16->setCheckable(true);
@@ -108,6 +121,8 @@ void RegisterWindow::contextMenuEvent(QContextMenuEvent *ev)
reloadContents();
else if (act == actAlwaysReload)
setAlwaysReloadContents(!m_alwaysReloadContents);
+ else if (act == actShowMemory)
+ (void) new MemoryViewAgent(m_manager, address);
else if (act) {
base = (act == act10 ? 10 : act == act8 ? 8 : act == act2 ? 2 : 16);
QMetaObject::invokeMethod(model(), "setNumberBase", Q_ARG(int, base));
diff --git a/src/plugins/debugger/registerwindow.h b/src/plugins/debugger/registerwindow.h
index 4839c796137..f29283f3b54 100644
--- a/src/plugins/debugger/registerwindow.h
+++ b/src/plugins/debugger/registerwindow.h
@@ -35,12 +35,14 @@
namespace Debugger {
namespace Internal {
+class DebuggerManager;
+
class RegisterWindow : public QTreeView
{
Q_OBJECT
public:
- RegisterWindow();
+ explicit RegisterWindow(DebuggerManager *manager);
void setModel(QAbstractItemModel *model);
signals:
@@ -57,6 +59,8 @@ private:
void resizeEvent(QResizeEvent *ev);
void contextMenuEvent(QContextMenuEvent *ev);
+ DebuggerManager *m_manager;
+
bool m_alwaysResizeColumnsToContents;
bool m_alwaysReloadContents;
};
diff --git a/src/plugins/debugger/script/scriptengine.cpp b/src/plugins/debugger/script/scriptengine.cpp
index a6f099ac9a3..44a9f610fc1 100644
--- a/src/plugins/debugger/script/scriptengine.cpp
+++ b/src/plugins/debugger/script/scriptengine.cpp
@@ -565,7 +565,10 @@ void ScriptEngine::maybeBreakNow(bool byFunction)
}
qq->notifyInferiorStopped();
- q->gotoLocation(fileName, lineNumber, true);
+ StackFrame frame;
+ frame.file = fileName;
+ frame.line = lineNumber;
+ q->gotoLocation(frame, true);
updateLocals();
}
diff --git a/src/plugins/debugger/stackframe.h b/src/plugins/debugger/stackframe.h
new file mode 100644
index 00000000000..35108aef3ef
--- /dev/null
+++ b/src/plugins/debugger/stackframe.h
@@ -0,0 +1,60 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation ([email protected])
+**
+** 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_STACKFRAME_H
+#define DEBUGGER_STACKFRAME_H
+
+#include <QtCore/QString>
+#include <QtCore/QVariant>
+
+namespace Debugger {
+namespace Internal {
+
+struct StackFrame
+{
+ StackFrame(int level = 0);
+ bool isUsable() const;
+ QString toToolTip() const;
+ QString toString() const;
+
+ int level;
+ QString function;
+ QString file; // we try to put an absolute file name in there
+ QString from;
+ QString to;
+ int line;
+ QString address;
+};
+
+} // namespace Internal
+} // namespace Debugger
+
+Q_DECLARE_METATYPE(Debugger::Internal::StackFrame);
+
+#endif // DEBUGGER_STACKFRAME_H
diff --git a/src/plugins/debugger/stackhandler.cpp b/src/plugins/debugger/stackhandler.cpp
index c315e4f9b64..e5bd3879f64 100644
--- a/src/plugins/debugger/stackhandler.cpp
+++ b/src/plugins/debugger/stackhandler.cpp
@@ -29,6 +29,8 @@
#include "stackhandler.h"
+#include "debuggeractions.h"
+
#include <utils/qtcassert.h>
#include <QtCore/QAbstractTableModel>
@@ -46,6 +48,19 @@ bool StackFrame::isUsable() const
return !file.isEmpty() && QFileInfo(file).isReadable();
}
+QString StackFrame::toString() const
+{
+ QString res;
+ QTextStream str(&res);
+ str << StackHandler::tr("Address:") << " " << address << " "
+ << StackHandler::tr("Function:") << " " << function << " "
+ << StackHandler::tr("File:") << " " << file << " "
+ << StackHandler::tr("Line:") << " " << line << " "
+ << StackHandler::tr("From:") << " " << from << " "
+ << StackHandler::tr("To:") << " " << to;
+ return res;
+}
+
QString StackFrame::toToolTip() const
{
QString res;
@@ -117,14 +132,22 @@ QVariant StackHandler::data(const QModelIndex &index, int role) const
case 4: // Address
return frame.address;
}
- } else if (role == Qt::ToolTipRole) {
+ return QVariant();
+ }
+
+ if (role == Qt::ToolTipRole) {
//: Tooltip for variable
return frame.toToolTip();
- } else if (role == Qt::DecorationRole && index.column() == 0) {
+ }
+
+ if (role == Qt::DecorationRole && index.column() == 0) {
// Return icon that indicates whether this is the active stack frame
return (index.row() == m_currentIndex) ? m_positionIcon : m_emptyIcon;
}
+ if (role == Qt::UserRole)
+ return QVariant::fromValue(frame);
+
return QVariant();
}
@@ -149,7 +172,8 @@ Qt::ItemFlags StackHandler::flags(const QModelIndex &index) const
if (index.row() == m_stackFrames.size())
return QAbstractTableModel::flags(index);
const StackFrame &frame = m_stackFrames.at(index.row());
- const bool isValid = (!frame.file.isEmpty() && !frame.function.isEmpty());
+ const bool isValid = (!frame.file.isEmpty() && !frame.function.isEmpty())
+ || theDebuggerBoolSetting(StepByInstruction);
return isValid ? QAbstractTableModel::flags(index) : Qt::ItemFlags(0);
}
diff --git a/src/plugins/debugger/stackhandler.h b/src/plugins/debugger/stackhandler.h
index 63f49e6c525..3fee2a5f872 100644
--- a/src/plugins/debugger/stackhandler.h
+++ b/src/plugins/debugger/stackhandler.h
@@ -30,11 +30,14 @@
#ifndef DEBUGGER_STACKHANDLER_H
#define DEBUGGER_STACKHANDLER_H
+#include "stackframe.h"
+
#include <QtCore/QAbstractTableModel>
#include <QtCore/QObject>
#include <QtGui/QIcon>
+
namespace Debugger {
namespace Internal {
@@ -44,21 +47,6 @@ namespace Internal {
//
////////////////////////////////////////////////////////////////////////
-struct StackFrame
-{
- StackFrame(int level = 0);
- bool isUsable() const;
- QString toToolTip() const;
-
- int level;
- QString function;
- QString file; // we try to put an absolute file name in there
- QString from;
- QString to;
- int line;
- QString address;
-};
-
/*! A model to represent the stack in a QTreeView. */
class StackHandler : public QAbstractTableModel
{
diff --git a/src/plugins/debugger/stackwindow.cpp b/src/plugins/debugger/stackwindow.cpp
index 2bb9d721b7b..1f397b5114f 100644
--- a/src/plugins/debugger/stackwindow.cpp
+++ b/src/plugins/debugger/stackwindow.cpp
@@ -28,8 +28,10 @@
**************************************************************************/
#include "stackwindow.h"
+#include "stackframe.h"
#include "debuggeractions.h"
+#include "debuggeragents.h"
#include <utils/qtcassert.h>
@@ -46,11 +48,14 @@
#include <QtGui/QVBoxLayout>
-using Debugger::Internal::StackWindow;
+namespace Debugger {
+namespace Internal {
-StackWindow::StackWindow(QWidget *parent)
- : QTreeView(parent), m_alwaysResizeColumnsToContents(false)
+StackWindow::StackWindow(DebuggerManager *manager, QWidget *parent)
+ : QTreeView(parent), m_manager(manager), m_alwaysResizeColumnsToContents(false)
{
+ m_disassemblerAgent = new DisassemblerViewAgent(manager);
+
QAction *act = theDebuggerAction(UseAlternatingRowColors);
setWindowTitle(tr("Stack"));
@@ -90,33 +95,60 @@ void StackWindow::rowActivated(const QModelIndex &index)
void StackWindow::contextMenuEvent(QContextMenuEvent *ev)
{
+ QModelIndex idx = indexAt(ev->pos());
+ StackFrame frame = model()->data(idx, Qt::UserRole).value<StackFrame>();
+ QString address = frame.address;
+
+ qDebug() << "RECV: " << frame.toToolTip();
+
QMenu menu;
- QAction *act0 = new QAction(tr("Copy contents to clipboard"), &menu);
- act0->setEnabled(model() != 0);
+ QAction *actAdjust = menu.addAction(tr("Adjust column widths to contents"));
- QAction *act1 = new QAction(tr("Adjust column widths to contents"), &menu);
+ QAction *actAlwaysAdjust =
+ menu.addAction(tr("Always adjust column widths to contents"));
+ actAlwaysAdjust->setCheckable(true);
+ actAlwaysAdjust->setChecked(m_alwaysResizeColumnsToContents);
- QAction *act2 = new QAction(tr("Always adjust column widths to contents"), &menu);
- act2->setCheckable(true);
- act2->setChecked(m_alwaysResizeColumnsToContents);
+ menu.addSeparator();
menu.addAction(theDebuggerAction(ExpandStack));
- menu.addAction(act0);
- menu.addSeparator();
- menu.addAction(act1);
- menu.addAction(act2);
+
+ QAction *actCopyContents = menu.addAction(tr("Copy contents to clipboard"));
+ actCopyContents->setEnabled(model() != 0);
+
+ QAction *actShowMemory = menu.addAction(QString());
+ if (address.isEmpty()) {
+ actShowMemory->setText(tr("Open memory editor"));
+ actShowMemory->setEnabled(false);
+ } else {
+ actShowMemory->setText(tr("Open memory editor at %1").arg(address));
+ }
+
+ QAction *actShowDisassembler = menu.addAction(QString());
+ if (address.isEmpty()) {
+ actShowDisassembler->setText(tr("Open disassembler"));
+ actShowDisassembler->setEnabled(false);
+ } else {
+ actShowDisassembler->setText(tr("Open disassembler at %1").arg(address));
+ }
+
menu.addSeparator();
+
menu.addAction(theDebuggerAction(SettingsDialog));
QAction *act = menu.exec(ev->globalPos());
- if (act == act0)
+ if (act == actCopyContents)
copyContentsToClipboard();
- else if (act == act1)
+ else if (act == actAdjust)
resizeColumnsToContents();
- else if (act == act2)
+ else if (act == actAlwaysAdjust)
setAlwaysResizeColumnsToContents(!m_alwaysResizeColumnsToContents);
+ else if (act == actShowMemory)
+ (void) new MemoryViewAgent(m_manager, address);
+ else if (act == actShowDisassembler)
+ m_disassemblerAgent->setFrame(frame);
}
void StackWindow::copyContentsToClipboard()
@@ -157,3 +189,6 @@ void StackWindow::setAlwaysResizeColumnsToContents(bool on)
header()->setResizeMode(2, mode);
header()->setResizeMode(3, mode);
}
+
+} // namespace Internal
+} // namespace Debugger
diff --git a/src/plugins/debugger/stackwindow.h b/src/plugins/debugger/stackwindow.h
index 42bc03749ce..2703735420e 100644
--- a/src/plugins/debugger/stackwindow.h
+++ b/src/plugins/debugger/stackwindow.h
@@ -40,13 +40,16 @@ QT_END_NAMESPACE
namespace Debugger {
namespace Internal {
+
+class DebuggerManager;
+class DisassemblerViewAgent;
class StackWindow : public QTreeView
{
Q_OBJECT
public:
- StackWindow(QWidget *parent = 0);
+ StackWindow(DebuggerManager *manager, QWidget *parent = 0);
signals:
void frameActivated(int);
@@ -64,6 +67,8 @@ private:
void contextMenuEvent(QContextMenuEvent *ev);
void copyContentsToClipboard();
+ DebuggerManager *m_manager;
+ DisassemblerViewAgent *m_disassemblerAgent;
bool m_alwaysResizeColumnsToContents;
};
diff --git a/src/plugins/debugger/watchwindow.cpp b/src/plugins/debugger/watchwindow.cpp
index 6d090bf585a..a41c6721a9a 100644
--- a/src/plugins/debugger/watchwindow.cpp
+++ b/src/plugins/debugger/watchwindow.cpp
@@ -297,9 +297,7 @@ void WatchWindow::contextMenuEvent(QContextMenuEvent *ev)
theDebuggerAction(WatchExpression)
->trigger(WatchHandler::watcherEditPlaceHolder());
} else if (act == actWatchKnownMemory) {
- bool ok = true;
- uint addr = address.toUInt(&ok, 0);
- (void) new MemoryViewAgent(m_manager, addr);
+ (void) new MemoryViewAgent(m_manager, address);
} else if (act == actWatchUnknownMemory) {
QLabel *label = new QLabel("Enter an address: ");
QLineEdit *lineEdit = new QLineEdit;
@@ -310,11 +308,8 @@ void WatchWindow::contextMenuEvent(QContextMenuEvent *ev)
dialog.setWindowTitle("Select start address");
dialog.setLayout(layout);
connect(lineEdit, SIGNAL(returnPressed()), &dialog, SLOT(accept()));
- if (dialog.exec() == QDialog::Accepted) {
- bool ok = true;
- uint addr = lineEdit->text().toUInt(&ok, 0);
- (void) new MemoryViewAgent(m_manager, addr);
- }
+ if (dialog.exec() == QDialog::Accepted)
+ (void) new MemoryViewAgent(m_manager, address);
} else if (act == actSelectWidgetToWatch) {
grabMouse(Qt::CrossCursor);
m_grabbing = true;