diff options
author | hjk <[email protected]> | 2015-07-20 09:37:54 +0200 |
---|---|---|
committer | hjk <[email protected]> | 2015-07-22 11:46:32 +0000 |
commit | d765cd73a2292ccad36837aca696808b5d2cdacd (patch) | |
tree | 3d8c27af67d3af53094ef8ade0ec39abd4704736 /src/plugins | |
parent | e3c2236c266da0020bac8b1904a72d9ffc879700 (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')
-rw-r--r-- | src/plugins/debugger/debuggerengine.cpp | 7 | ||||
-rw-r--r-- | src/plugins/debugger/debuggerengine.h | 9 | ||||
-rw-r--r-- | src/plugins/debugger/debuggerinternalconstants.h | 1 | ||||
-rw-r--r-- | src/plugins/debugger/debuggerplugin.cpp | 146 | ||||
-rw-r--r-- | src/plugins/debugger/disassembleragent.cpp | 16 | ||||
-rw-r--r-- | src/plugins/debugger/disassemblerlines.cpp | 9 | ||||
-rw-r--r-- | src/plugins/debugger/disassemblerlines.h | 3 | ||||
-rw-r--r-- | src/plugins/debugger/sourceutils.cpp | 26 |
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; |