aboutsummaryrefslogtreecommitdiffstats
path: root/src/plugins/debugger
diff options
context:
space:
mode:
authorhjk <[email protected]>2015-07-20 09:37:54 +0200
committerhjk <[email protected]>2015-07-22 11:46:32 +0000
commitd765cd73a2292ccad36837aca696808b5d2cdacd (patch)
tree3d8c27af67d3af53094ef8ade0ec39abd4704736 /src/plugins/debugger
parente3c2236c266da0020bac8b1904a72d9ffc879700 (diff)
Debugger: Recognize source data within disassembler view
... and use it to toggle breakpoints by file and line, and for jumping to file and line. Task-number: QTCREATORBUG-14278 Change-Id: I799d085eb53339905ea3608022aeae5a9aef1fda Reviewed-by: Niels Weber <[email protected]> Reviewed-by: Christian Stenger <[email protected]>
Diffstat (limited to 'src/plugins/debugger')
-rw-r--r--src/plugins/debugger/debuggerengine.cpp7
-rw-r--r--src/plugins/debugger/debuggerengine.h9
-rw-r--r--src/plugins/debugger/debuggerinternalconstants.h1
-rw-r--r--src/plugins/debugger/debuggerplugin.cpp146
-rw-r--r--src/plugins/debugger/disassembleragent.cpp16
-rw-r--r--src/plugins/debugger/disassemblerlines.cpp9
-rw-r--r--src/plugins/debugger/disassemblerlines.h3
-rw-r--r--src/plugins/debugger/sourceutils.cpp26
8 files changed, 114 insertions, 103 deletions
diff --git a/src/plugins/debugger/debuggerengine.cpp b/src/plugins/debugger/debuggerengine.cpp
index ef0b4427c7c..950ffb1e86d 100644
--- a/src/plugins/debugger/debuggerengine.cpp
+++ b/src/plugins/debugger/debuggerengine.cpp
@@ -150,8 +150,11 @@ bool LocationMark::isDraggable() const
void LocationMark::dragToLine(int line)
{
if (m_engine) {
- if (BaseTextEditor *textEditor = BaseTextEditor::currentTextEditor())
- m_engine->executeJumpToLine(getLocationContext(textEditor->textDocument(), line));
+ if (BaseTextEditor *textEditor = BaseTextEditor::currentTextEditor()) {
+ ContextData location = getLocationContext(textEditor->textDocument(), line);
+ if (location.isValid())
+ m_engine->executeJumpToLine(location);
+ }
}
}
diff --git a/src/plugins/debugger/debuggerengine.h b/src/plugins/debugger/debuggerengine.h
index 86a2abfb42d..f62a7e381bc 100644
--- a/src/plugins/debugger/debuggerengine.h
+++ b/src/plugins/debugger/debuggerengine.h
@@ -170,15 +170,18 @@ private:
quint64 m_address;
};
+enum LocationType { UnknownLocation, LocationByFile, LocationByAddress };
+
class ContextData
{
public:
- ContextData() : lineNumber(0), address(0) {}
+ bool isValid() const { return type != UnknownLocation; }
public:
+ LocationType type = UnknownLocation;
QString fileName;
- int lineNumber;
- quint64 address;
+ int lineNumber = 0;
+ quint64 address = 0;
};
class DebuggerEngine : public QObject
diff --git a/src/plugins/debugger/debuggerinternalconstants.h b/src/plugins/debugger/debuggerinternalconstants.h
index 576ed7a82aa..290edbde3f7 100644
--- a/src/plugins/debugger/debuggerinternalconstants.h
+++ b/src/plugins/debugger/debuggerinternalconstants.h
@@ -47,6 +47,7 @@ namespace Internal {
const char OPENED_BY_DEBUGGER[] = "OpenedByDebugger";
const char OPENED_WITH_DISASSEMBLY[] = "DisassemblerView";
+const char DISASSEMBLER_SOURCE_FILE[] = "DisassemblerSourceFile";
// Debug action
const char DEBUG[] = "Debugger.Debug";
diff --git a/src/plugins/debugger/debuggerplugin.cpp b/src/plugins/debugger/debuggerplugin.cpp
index 97746ea22f0..bf2b4f98fc3 100644
--- a/src/plugins/debugger/debuggerplugin.cpp
+++ b/src/plugins/debugger/debuggerplugin.cpp
@@ -618,7 +618,7 @@ public:
{
QString message;
if (isMessageOnly) {
- if (data.address) {
+ if (data.type == LocationByAddress) {
//: Message tracepoint: Address hit.
message = tr("0x%1 hit").arg(data.address, 0, 16);
} else {
@@ -638,10 +638,7 @@ public:
return;
message = dialog.textValue();
}
- if (data.address)
- toggleBreakpointByAddress(data.address, message);
- else
- toggleBreakpointByFileAndLine(data.fileName, data.lineNumber, message);
+ toggleBreakpoint(data, message);
}
void updateWatchersHeader(int section, int, int newSize)
@@ -687,11 +684,8 @@ public:
void activatePreviousMode();
void activateDebugMode();
- void toggleBreakpoint();
- void toggleBreakpointByFileAndLine(const QString &fileName, int lineNumber,
- const QString &tracePointMessage = QString());
- void toggleBreakpointByAddress(quint64 address,
- const QString &tracePointMessage = QString());
+ void toggleBreakpointHelper();
+ void toggleBreakpoint(const ContextData &location, const QString &tracePointMessage = QString());
void onModeChanged(IMode *mode);
void onCoreAboutToOpen();
void updateDebugWithoutDeployMenu();
@@ -829,17 +823,23 @@ public slots:
void handleExecJumpToLine()
{
currentEngine()->resetLocation();
- if (BaseTextEditor *textEditor = BaseTextEditor::currentTextEditor())
- currentEngine()->executeJumpToLine(getLocationContext(textEditor->textDocument(),
- textEditor->currentLine()));
+ if (BaseTextEditor *textEditor = BaseTextEditor::currentTextEditor()) {
+ ContextData location = getLocationContext(textEditor->textDocument(),
+ textEditor->currentLine());
+ if (location.isValid())
+ currentEngine()->executeJumpToLine(location);
+ }
}
void handleExecRunToLine()
{
currentEngine()->resetLocation();
- if (BaseTextEditor *textEditor = BaseTextEditor::currentTextEditor())
- currentEngine()->executeRunToLine(getLocationContext(textEditor->textDocument(),
- textEditor->currentLine()));
+ if (BaseTextEditor *textEditor = BaseTextEditor::currentTextEditor()) {
+ ContextData location = getLocationContext(textEditor->textDocument(),
+ textEditor->currentLine());
+ if (location.isValid())
+ currentEngine()->executeRunToLine(location);
+ }
}
void handleExecRunToSelectedFunction()
@@ -1573,26 +1573,18 @@ void DebuggerPluginPrivate::updateBreakMenuItem(IEditor *editor)
void DebuggerPluginPrivate::requestContextMenu(TextEditorWidget *widget,
int lineNumber, QMenu *menu)
{
- ContextData args;
- args.lineNumber = lineNumber;
- bool contextUsable = true;
-
Breakpoint bp;
TextDocument *document = widget->textDocument();
- args.fileName = document->filePath().toString();
- if (document->property(Constants::OPENED_WITH_DISASSEMBLY).toBool()) {
- QString line = document->plainText()
- .section(QLatin1Char('\n'), lineNumber - 1, lineNumber - 1);
+
+ ContextData args = getLocationContext(document, lineNumber);
+ if (args.type == LocationByAddress) {
BreakpointResponse needle;
needle.type = BreakpointByAddress;
- needle.address = DisassemblerLine::addressFromDisassemblyLine(line);
- args.address = needle.address;
+ needle.address = args.address;
needle.lineNumber = -1;
bp = breakHandler()->findSimilarBreakpoint(needle);
- contextUsable = args.address != 0;
- } else {
- bp = breakHandler()
- ->findBreakpointByFileAndLine(args.fileName, lineNumber);
+ } else if (args.type == LocationByFile) {
+ bp = breakHandler()->findBreakpointByFileAndLine(args.fileName, lineNumber);
if (!bp)
bp = breakHandler()->findBreakpointByFileAndLine(args.fileName, lineNumber, false);
}
@@ -1625,7 +1617,7 @@ void DebuggerPluginPrivate::requestContextMenu(TextEditorWidget *widget,
? tr("Set Breakpoint at 0x%1").arg(args.address, 0, 16)
: tr("Set Breakpoint at Line %1").arg(lineNumber);
auto act = menu->addAction(text);
- act->setEnabled(contextUsable);
+ act->setEnabled(args.isValid());
connect(act, &QAction::triggered, [this, args] {
breakpointSetMarginActionTriggered(false, args);
});
@@ -1635,14 +1627,14 @@ void DebuggerPluginPrivate::requestContextMenu(TextEditorWidget *widget,
? tr("Set Message Tracepoint at 0x%1...").arg(args.address, 0, 16)
: tr("Set Message Tracepoint at Line %1...").arg(lineNumber);
act = menu->addAction(tracePointText);
- act->setEnabled(contextUsable);
+ act->setEnabled(args.isValid());
connect(act, &QAction::triggered, [this, args] {
breakpointSetMarginActionTriggered(true, args);
});
}
// Run to, jump to line below in stopped state.
- if (currentEngine()->state() == InferiorStopOk && contextUsable) {
+ if (currentEngine()->state() == InferiorStopOk && args.isValid()) {
menu->addSeparator();
if (currentEngine()->hasCapability(RunToLineCapability)) {
auto act = menu->addAction(args.address
@@ -1678,72 +1670,58 @@ void DebuggerPluginPrivate::requestContextMenu(TextEditorWidget *widget,
}
}
-void DebuggerPluginPrivate::toggleBreakpoint()
-{
- BaseTextEditor *textEditor = BaseTextEditor::currentTextEditor();
- QTC_ASSERT(textEditor, return);
- const int lineNumber = textEditor->currentLine();
- if (textEditor->property(Constants::OPENED_WITH_DISASSEMBLY).toBool()) {
- QString line = textEditor->textDocument()->plainText()
- .section(QLatin1Char('\n'), lineNumber - 1, lineNumber - 1);
- quint64 address = DisassemblerLine::addressFromDisassemblyLine(line);
- toggleBreakpointByAddress(address);
- } else if (lineNumber >= 0) {
- toggleBreakpointByFileAndLine(textEditor->document()->filePath().toString(), lineNumber);
- }
-}
-
-void DebuggerPluginPrivate::toggleBreakpointByFileAndLine(const QString &fileName,
- int lineNumber, const QString &tracePointMessage)
+void DebuggerPluginPrivate::toggleBreakpoint(const ContextData &location, const QString &tracePointMessage)
{
+ QTC_ASSERT(location.isValid(), return);
BreakHandler *handler = m_breakHandler;
- Breakpoint bp = handler->findBreakpointByFileAndLine(fileName, lineNumber, true);
- if (!bp)
- bp = handler->findBreakpointByFileAndLine(fileName, lineNumber, false);
+ Breakpoint bp;
+ if (location.type == LocationByFile) {
+ bp = handler->findBreakpointByFileAndLine(location.fileName, location.lineNumber, true);
+ if (!bp)
+ bp = handler->findBreakpointByFileAndLine(location.fileName, location.lineNumber, false);
+ } else if (location.type == LocationByAddress) {
+ bp = handler->findBreakpointByAddress(location.address);
+ }
if (bp) {
bp.removeBreakpoint();
} else {
- BreakpointParameters data(BreakpointByFileAndLine);
- if (boolSetting(BreakpointsFullPathByDefault))
- data.pathUsage = BreakpointUseFullPath;
- data.tracepoint = !tracePointMessage.isEmpty();
- data.message = tracePointMessage;
- data.fileName = fileName;
- data.lineNumber = lineNumber;
+ BreakpointParameters data;
+ if (location.type == LocationByFile) {
+ data.type = BreakpointByFileAndLine;
+ if (boolSetting(BreakpointsFullPathByDefault))
+ data.pathUsage = BreakpointUseFullPath;
+ data.tracepoint = !tracePointMessage.isEmpty();
+ data.message = tracePointMessage;
+ data.fileName = location.fileName;
+ data.lineNumber = location.lineNumber;
+ } else if (location.type == LocationByAddress) {
+ data.type = BreakpointByAddress;
+ data.tracepoint = !tracePointMessage.isEmpty();
+ data.message = tracePointMessage;
+ data.address = location.address;
+ }
handler->appendBreakpoint(data);
}
}
-void DebuggerPluginPrivate::toggleBreakpointByAddress(quint64 address,
- const QString &tracePointMessage)
+void DebuggerPluginPrivate::toggleBreakpointHelper()
{
- BreakHandler *handler = m_breakHandler;
- if (Breakpoint bp = handler->findBreakpointByAddress(address)) {
- bp.removeBreakpoint();
- } else {
- BreakpointParameters data(BreakpointByAddress);
- data.tracepoint = !tracePointMessage.isEmpty();
- data.message = tracePointMessage;
- data.address = address;
- handler->appendBreakpoint(data);
- }
+ BaseTextEditor *textEditor = BaseTextEditor::currentTextEditor();
+ QTC_ASSERT(textEditor, return);
+ const int lineNumber = textEditor->currentLine();
+ ContextData location = getLocationContext(textEditor->textDocument(), lineNumber);
+ if (location.isValid())
+ toggleBreakpoint(location);
}
void DebuggerPluginPrivate::requestMark(TextEditorWidget *widget, int lineNumber,
TextMarkRequestKind kind)
{
- if (kind != BreakpointRequest)
- return;
-
- TextDocument *document = widget->textDocument();
- if (document->property(Constants::OPENED_WITH_DISASSEMBLY).toBool()) {
- QString line = document->plainText()
- .section(QLatin1Char('\n'), lineNumber - 1, lineNumber - 1);
- quint64 address = DisassemblerLine::addressFromDisassemblyLine(line);
- toggleBreakpointByAddress(address);
- } else {
- toggleBreakpointByFileAndLine(document->filePath().toString(), lineNumber);
+ if (kind == BreakpointRequest) {
+ ContextData location = getLocationContext(widget->textDocument(), lineNumber);
+ if (location.isValid())
+ toggleBreakpoint(location);
}
}
@@ -2801,7 +2779,7 @@ void DebuggerPluginPrivate::extensionsInitialized()
cmd->setDefaultKeySequence(QKeySequence(UseMacShortcuts ? tr("F8") : tr("F9")));
debugMenu->addAction(cmd);
connect(m_breakAction, &QAction::triggered,
- this, &DebuggerPluginPrivate::toggleBreakpoint);
+ this, &DebuggerPluginPrivate::toggleBreakpointHelper);
debugMenu->addSeparator();
diff --git a/src/plugins/debugger/disassembleragent.cpp b/src/plugins/debugger/disassembleragent.cpp
index e6f5632ff7c..77128756936 100644
--- a/src/plugins/debugger/disassembleragent.cpp
+++ b/src/plugins/debugger/disassembleragent.cpp
@@ -38,6 +38,7 @@
#include "debuggerstartparameters.h"
#include "debuggerstringutils.h"
#include "disassemblerlines.h"
+#include "sourceutils.h"
#include <coreplugin/coreconstants.h>
#include <coreplugin/icore.h>
@@ -292,10 +293,13 @@ void DisassemblerAgent::setContentsToDocument(const DisassemblerLines &contents)
widget->setReadOnly(true);
widget->setRequestMarkEnabled(true);
}
+ // FIXME: This is accumulating quite a bit out-of-band data.
+ // Make that a proper TextDocument reimplementation.
d->document = qobject_cast<TextDocument *>(editor->document());
QTC_ASSERT(d->document, return);
d->document->setProperty(Debugger::Constants::OPENED_BY_DEBUGGER, true);
d->document->setProperty(Debugger::Constants::OPENED_WITH_DISASSEMBLY, true);
+ d->document->setProperty(Debugger::Constants::DISASSEMBLER_SOURCE_FILE, d->location.fileName());
d->configureMimeType();
} else {
EditorManager::activateEditorForDocument(d->document);
@@ -345,9 +349,19 @@ void DisassemblerAgent::updateBreakpointMarkers()
const quint64 address = bp.response().address;
if (!address)
continue;
- const int lineNumber = contents.lineForAddress(address);
+ int lineNumber = contents.lineForAddress(address);
if (!lineNumber)
continue;
+
+ // HACK: If it's a FileAndLine breakpoint, and there's a source line
+ // above, move the marker up there. That allows setting and removing
+ // normal breakpoints from within the disassembler view.
+ if (bp.type() == BreakpointByFileAndLine) {
+ ContextData context = getLocationContext(d->document, lineNumber - 1);
+ if (context.type == LocationByFile)
+ --lineNumber;
+ }
+
TextMark *marker = new TextMark(QString(), lineNumber,
Constants::TEXT_MARK_CATEGORY_BREAKPOINT);
marker->setIcon(bp.icon());
diff --git a/src/plugins/debugger/disassemblerlines.cpp b/src/plugins/debugger/disassemblerlines.cpp
index f769f827b3d..83d078447d6 100644
--- a/src/plugins/debugger/disassemblerlines.cpp
+++ b/src/plugins/debugger/disassemblerlines.cpp
@@ -29,7 +29,9 @@
****************************************************************************/
#include "disassemblerlines.h"
+#include "debuggerengine.h"
#include "debuggerstringutils.h"
+#include "sourceutils.h"
#include <QDebug>
#include <QFile>
@@ -72,13 +74,6 @@ void DisassemblerLine::fromString(const QString &unparsed)
data = unparsed;
}
-quint64 DisassemblerLine::addressFromDisassemblyLine(const QString &line)
-{
- DisassemblerLine l;
- l.fromString(line);
- return l.address;
-}
-
quint64 DisassemblerLines::startAddress() const
{
for (int i = 0; i < m_data.size(); ++i)
diff --git a/src/plugins/debugger/disassemblerlines.h b/src/plugins/debugger/disassemblerlines.h
index c968546c1c9..ee91e58aaeb 100644
--- a/src/plugins/debugger/disassemblerlines.h
+++ b/src/plugins/debugger/disassemblerlines.h
@@ -53,9 +53,6 @@ public:
QString toString(int maxOp = 0) const;
void fromString(const QString &unparsed);
- // Return address of an assembly line "0x0dfd bla".
- static quint64 addressFromDisassemblyLine(const QString &line);
-
public:
quint64 address; // (ass) Address of instruction in memory/in binary.
QString function; // (ass) Function to which current instruction belongs.
diff --git a/src/plugins/debugger/sourceutils.cpp b/src/plugins/debugger/sourceutils.cpp
index 5da06340b40..2e55dc8cbdc 100644
--- a/src/plugins/debugger/sourceutils.cpp
+++ b/src/plugins/debugger/sourceutils.cpp
@@ -48,6 +48,8 @@
#include <utils/qtcassert.h>
#include <QDebug>
+#include <QTextDocument>
+#include <QTextBlock>
#include <string.h>
#include <ctype.h>
@@ -340,11 +342,29 @@ ContextData getLocationContext(TextDocument *document, int lineNumber)
{
ContextData data;
QTC_ASSERT(document, return data);
- data.fileName = document->filePath().toString();
if (document->property(Constants::OPENED_WITH_DISASSEMBLY).toBool()) {
- QString line = document->plainText().section(QLatin1Char('\n'), lineNumber - 1, lineNumber - 1);
- data.address = DisassemblerLine::addressFromDisassemblyLine(line);
+ QString line = document->document()->findBlockByNumber(lineNumber - 1).text();
+ DisassemblerLine l;
+ l.fromString(line);
+ if (l.address) {
+ data.type = LocationByAddress;
+ data.address = l.address;
+ } else {
+ QString fileName = document->property(Constants::DISASSEMBLER_SOURCE_FILE).toString();
+ if (!fileName.isEmpty()) {
+ // Possibly one of the "27 [1] foo = x" lines
+ int pos = line.indexOf(QLatin1Char('['));
+ int ln = line.left(pos - 1).toInt();
+ if (ln > 0) {
+ data.type = LocationByFile;
+ data.fileName = fileName;
+ data.lineNumber = ln;
+ }
+ }
+ }
} else {
+ data.type = LocationByFile;
+ data.fileName = document->filePath().toString();
data.lineNumber = lineNumber;
}
return data;