From 9757e221135f6fac27a10791316e61d20c33ec30 Mon Sep 17 00:00:00 2001 From: hjk Date: Thu, 16 Dec 2010 19:06:33 +0100 Subject: [PATCH] debugger: introduce the concept of a 'Location', used by gotoLocation --- src/plugins/debugger/breakhandler.cpp | 9 ++-- src/plugins/debugger/cdb/cdbengine.cpp | 4 +- src/plugins/debugger/cdb2/cdbengine2.cpp | 6 +-- src/plugins/debugger/debuggerengine.cpp | 26 +++++----- src/plugins/debugger/debuggerengine.h | 45 ++++++++++++++++-- src/plugins/debugger/debuggerplugin.cpp | 5 +- src/plugins/debugger/disassembleragent.cpp | 50 ++++++++++---------- src/plugins/debugger/disassembleragent.h | 8 ++-- src/plugins/debugger/gdb/gdbengine.cpp | 10 ++-- src/plugins/debugger/lldb/ipcenginehost.cpp | 4 +- src/plugins/debugger/pdb/pdbengine.cpp | 6 +-- src/plugins/debugger/qml/qmlengine.cpp | 23 +++------ src/plugins/debugger/qml/qmlengine.h | 4 +- src/plugins/debugger/script/scriptengine.cpp | 6 +-- 14 files changed, 112 insertions(+), 94 deletions(-) diff --git a/src/plugins/debugger/breakhandler.cpp b/src/plugins/debugger/breakhandler.cpp index bfcd8cb9def..06026ddab4c 100644 --- a/src/plugins/debugger/breakhandler.cpp +++ b/src/plugins/debugger/breakhandler.cpp @@ -894,15 +894,12 @@ void BreakHandler::gotoLocation(BreakpointId id) const QTC_ASSERT(it != m_storage.end(), return); DebuggerEngine *engine = debuggerCore()->currentEngine(); if (it->data.type == BreakpointByAddress) { - StackFrame frame; - frame.address = it->data.address; if (engine) - engine->gotoLocation(frame, false); + engine->gotoLocation(it->data.address); } else { - const QString fileName = it->markerFileName(); - const int lineNumber = it->markerLineNumber(); if (engine) - engine->gotoLocation(fileName, lineNumber, false); + engine->gotoLocation( + Location(it->markerFileName(), it->markerLineNumber())); } } diff --git a/src/plugins/debugger/cdb/cdbengine.cpp b/src/plugins/debugger/cdb/cdbengine.cpp index 2a356fdff4c..578703a1275 100644 --- a/src/plugins/debugger/cdb/cdbengine.cpp +++ b/src/plugins/debugger/cdb/cdbengine.cpp @@ -1049,7 +1049,7 @@ void CdbEngine::executeJumpToLine(const QString &fileName, int lineNumber) frame.usable = true; frame.file = fileName; frame.line = lineNumber; - gotoLocation(frame, true); + gotoLocation(frame); success = true; } while (false); if (!success) @@ -1166,7 +1166,7 @@ void CdbEngine::activateFrame(int frameIndex) break; } - gotoLocation(frame, true); + gotoLocation(frame); if (oldIndex != frameIndex || m_d->m_firstActivatedFrame) { watchHandler()->beginCycle(); diff --git a/src/plugins/debugger/cdb2/cdbengine2.cpp b/src/plugins/debugger/cdb2/cdbengine2.cpp index 43439c3a36b..0b92f5527c1 100644 --- a/src/plugins/debugger/cdb2/cdbengine2.cpp +++ b/src/plugins/debugger/cdb2/cdbengine2.cpp @@ -831,7 +831,7 @@ void CdbEngine::handleJumpToLineAddressResolution(const CdbBuiltinCommandPtr &cm // PC-register depending on 64/32bit. str << "r " << (m_options->is64bit ? "rip" : "eip") << "=0x" << answer; postCommand(registerCmd, 0); - gotoLocation(cookie.fileName, cookie.lineNumber, true); + gotoLocation(Location(cookie.fileName, cookie.lineNumber)); } void CdbEngine::assignValueInDebugger(const Debugger::Internal::WatchData *w, const QString &expr, const QVariant &value) @@ -979,13 +979,13 @@ void CdbEngine::activateFrame(int index) watchHandler()->endCycle(); QAction *assemblerAction = theAssemblerAction(); if (assemblerAction->isChecked()) { - gotoLocation(frame, true); + gotoLocation(frame); } else { assemblerAction->trigger(); // Seems to trigger update } return; } - gotoLocation(frame, true); + gotoLocation(frame); // Watchers: Initial expand, get uninitialized and query QByteArray arguments; ByteArrayInputStream str(arguments); diff --git a/src/plugins/debugger/debuggerengine.cpp b/src/plugins/debugger/debuggerengine.cpp index f12052063f6..ffec2314fdd 100644 --- a/src/plugins/debugger/debuggerengine.cpp +++ b/src/plugins/debugger/debuggerengine.cpp @@ -512,14 +512,21 @@ void DebuggerEngine::resetLocation() d->removeLocationMark(); } -void DebuggerEngine::gotoLocation(const QString &file, int line, bool setMarker) +void DebuggerEngine::gotoLocation(const Location &loc) { + if (debuggerCore()->boolSetting(OperateByInstruction) || !loc.hasDebugInfo()) { + d->m_disassemblerAgent.setTryMixed(true); + d->m_disassemblerAgent.setLocation(loc); + return; + } // CDB might hit on breakpoints while shutting down. //if (m_shuttingDown) // return; d->doRemoveLocationMark(); + const QString file = loc.fileName(); + const int line = loc.lineNumber(); EditorManager *editorManager = EditorManager::instance(); QList editors = editorManager->editorsForFileName(file); if (editors.isEmpty()) { @@ -531,23 +538,15 @@ void DebuggerEngine::gotoLocation(const QString &file, int line, bool setMarker) if (texteditor) texteditor->gotoLine(line, 0); - if (setMarker) + if (loc.needsMarker()) d->m_locationMark.reset(new LocationMark(file, line)); // FIXME: Breaks with split views. - if (!d->m_memoryAgent.hasVisibleEditor()) + if (!d->m_memoryAgent.hasVisibleEditor() || loc.needsRaise()) editorManager->activateEditor(editors.back()); //qDebug() << "MEMORY: " << d->m_memoryAgent.hasVisibleEditor(); } -void DebuggerEngine::gotoLocation(const StackFrame &frame, bool setMarker) -{ - if (debuggerCore()->boolSetting(OperateByInstruction) || !frame.isUsable()) - d->m_disassemblerAgent.setFrame(frame, true, setMarker); - else - gotoLocation(frame.file, frame.line, setMarker); -} - // Called from RunControl. void DebuggerEngine::handleStartFailed() { @@ -1469,10 +1468,11 @@ void DebuggerEngine::updateMemoryViews() d->m_memoryAgent.updateContents(); } -void DebuggerEngine::openDisassemblerView(const StackFrame &frame) +void DebuggerEngine::openDisassemblerView(const Location &location) { DisassemblerAgent *agent = new DisassemblerAgent(this); - agent->setFrame(frame, true, false); + agent->setTryMixed(true); + agent->setLocation(location); } void DebuggerEngine::handleRemoteSetupDone(int gdbServerPort, int qmlPort) diff --git a/src/plugins/debugger/debuggerengine.h b/src/plugins/debugger/debuggerengine.h index aec0adb6c89..1b8b4c0caf3 100644 --- a/src/plugins/debugger/debuggerengine.h +++ b/src/plugins/debugger/debuggerengine.h @@ -34,6 +34,7 @@ #include "debuggerconstants.h" #include "moduleshandler.h" // For 'Symbols' #include "breakpoint.h" // For 'BreakpointId' +#include "stackframe.h" #include @@ -141,6 +142,42 @@ struct WatchUpdateFlags bool tryIncremental; }; +class Location +{ +public: + Location() { init(); } + Location(quint64 address) { init(); m_address = address; } + Location(const QString &file) { init(); m_fileName = file; } + Location(const QString &file, int line, bool marker = true) + { init(); m_lineNumber = line; m_fileName = file; m_needsMarker = marker; } + Location(const StackFrame &frame, bool marker = true) //: m_frame(frame) + { init(); m_fileName = frame.file; m_lineNumber = frame.line; + m_needsMarker = marker; m_functionName = frame.function; + m_hasDebugInfo = frame.isUsable(); m_address = frame.address; } + QString fileName() const { return m_fileName; } + QString functionName() const { return m_functionName; } + int lineNumber() const { return m_lineNumber; } + void setNeedsRaise(bool on) { m_needsRaise = on; } + void setNeedsMarker(bool on) { m_needsMarker = on; } + void setFileName(const QString &fileName) { m_fileName = fileName; } + bool needsRaise() const { return m_needsRaise; } + bool needsMarker() const { return m_needsMarker; } + bool hasDebugInfo() const { return m_hasDebugInfo; } + quint64 address() const { return m_address; } + +private: + void init() { m_needsMarker = false; m_needsRaise = true; m_lineNumber = -1; + m_address = 0; m_hasDebugInfo = true; } + bool m_needsMarker; + bool m_needsRaise; + bool m_hasDebugInfo; + int m_lineNumber; + QString m_fileName; + QString m_functionName; + quint64 m_address; +}; + + } // namespace Internal @@ -166,7 +203,7 @@ public: virtual void fetchMemory(Internal::MemoryAgent *, QObject *, quint64 addr, quint64 length); virtual void updateMemoryViews(); - virtual void openDisassemblerView(const Internal::StackFrame &frame); + virtual void openDisassemblerView(const Internal::Location &location); virtual void fetchDisassembler(Internal::DisassemblerAgent *); virtual void activateFrame(int index); @@ -280,9 +317,7 @@ public: Q_SLOT void showStatusMessage(const QString &msg, int timeout = -1) const; void resetLocation(); - virtual void gotoLocation(const QString &fileName, int lineNumber = -1, - bool setMarker = false); - virtual void gotoLocation(const Internal::StackFrame &frame, bool setMarker); + virtual void gotoLocation(const Internal::Location &location); virtual void quitDebugger(); // called by DebuggerRunControl virtual void updateViews(); @@ -292,7 +327,7 @@ signals: void stateChanged(const DebuggerState &state); void updateViewsRequested(); /* - * For "external" clients of a debugger run control that need to do + * For "external" clients of a debugger run control that needs to do * further setup before the debugger is started (e.g. Maemo). * Afterwards, handleSetupDone() or handleSetupFailed() must be called * to continue or abort debugging, respectively. diff --git a/src/plugins/debugger/debuggerplugin.cpp b/src/plugins/debugger/debuggerplugin.cpp index 422bfe00340..b686f6de6d7 100644 --- a/src/plugins/debugger/debuggerplugin.cpp +++ b/src/plugins/debugger/debuggerplugin.cpp @@ -1240,8 +1240,9 @@ public slots: // Go to source only if we have the file. if (currentEngine()->stackHandler()->currentIndex() >= 0) { const StackFrame frame = currentEngine()->stackHandler()->currentFrame(); - if (operateByInstructionTriggered || frame.isUsable()) - currentEngine()->gotoLocation(frame, true); + if (operateByInstructionTriggered || frame.isUsable()) { + currentEngine()->gotoLocation(Location(frame, true)); + } } } diff --git a/src/plugins/debugger/disassembleragent.cpp b/src/plugins/debugger/disassembleragent.cpp index 1d7658260fb..5337451aebb 100644 --- a/src/plugins/debugger/disassembleragent.cpp +++ b/src/plugins/debugger/disassembleragent.cpp @@ -100,9 +100,8 @@ public: public: QPointer editor; - StackFrame frame; + Location location; bool tryMixed; - bool setMarker; QPointer engine; TextEditor::ITextMark *locationMark; QList breakpointMarks; @@ -114,7 +113,6 @@ public: DisassemblerAgentPrivate::DisassemblerAgentPrivate() : editor(0), tryMixed(true), - setMarker(true), locationMark(new LocationMark2), mimeType(_("text/x-qtcreator-generic-asm")) { @@ -162,36 +160,34 @@ void DisassemblerAgent::resetLocation() d->editor->markableInterface()->removeMark(d->locationMark); } -QString frameKey(const StackFrame &frame) +static QString frameKey(const Location &loc) { - return _("%1:%2:%3").arg(frame.function).arg(frame.file).arg(frame.from); + return _("%1:%2:%3").arg(loc.functionName()) + .arg(loc.fileName()).arg(loc.address()); } -const StackFrame &DisassemblerAgent::frame() const +const Location &DisassemblerAgent::location() const { - return d->frame; + return d->location; } bool DisassemblerAgent::isMixed() const { return d->tryMixed - && d->frame.line > 0 - && !d->frame.function.isEmpty() - && d->frame.function != _("??"); + && d->location.lineNumber() > 0 + && !d->location.functionName().isEmpty() + && d->location.functionName() != _("??"); } -void DisassemblerAgent::setFrame(const StackFrame &frame, - bool tryMixed, bool setMarker) +void DisassemblerAgent::setLocation(const Location &loc) { - d->frame = frame; - d->tryMixed = tryMixed; - d->setMarker = setMarker; + d->location = loc; if (isMixed()) { QHash::ConstIterator it = - d->cache.find(frameKey(frame)); + d->cache.find(frameKey(loc)); if (it != d->cache.end()) { QString msg = _("Use cache disassembler for '%1' in '%2'") - .arg(frame.function).arg(frame.file); + .arg(loc.functionName()).arg(loc.fileName()); d->engine->showMessage(msg); setContents(*it); updateBreakpointMarkers(); @@ -280,8 +276,9 @@ void DisassemblerAgent::setContents(const DisassemblerLines &contents) plainTextEdit->setPlainText(str); plainTextEdit->setReadOnly(true); - d->cache.insert(frameKey(d->frame), contents); - d->editor->setDisplayName(_("Disassembler (%1)").arg(d->frame.function)); + d->cache.insert(frameKey(d->location), contents); + d->editor->setDisplayName(_("Disassembler (%1)") + .arg(d->location.functionName())); updateBreakpointMarkers(); updateLocationMarker(); @@ -291,10 +288,10 @@ void DisassemblerAgent::updateLocationMarker() { QTC_ASSERT(d->editor, return); - const DisassemblerLines &contents = d->cache.value(frameKey(d->frame)); - int lineNumber = contents.lineForAddress(d->frame.address); + const DisassemblerLines &contents = d->cache.value(frameKey(d->location)); + int lineNumber = contents.lineForAddress(d->location.address()); - if (d->setMarker) { + if (d->location.needsMarker()) { d->editor->markableInterface()->removeMark(d->locationMark); if (lineNumber) d->editor->markableInterface()->addMark(d->locationMark, lineNumber); @@ -319,7 +316,7 @@ void DisassemblerAgent::updateBreakpointMarkers() if (ids.isEmpty()) return; - const DisassemblerLines &contents = d->cache.value(frameKey(d->frame)); + const DisassemblerLines &contents = d->cache.value(frameKey(d->location)); foreach (TextEditor::ITextMark *marker, d->breakpointMarks) d->editor->markableInterface()->removeMark(marker); @@ -339,7 +336,7 @@ void DisassemblerAgent::updateBreakpointMarkers() quint64 DisassemblerAgent::address() const { - return d->frame.address; + return d->location.address(); } // Return address of an assembly line "0x0dfd bla" @@ -348,5 +345,10 @@ quint64 DisassemblerAgent::addressFromDisassemblyLine(const QString &line) return DisassemblerLine(line).address; } +void DisassemblerAgent::setTryMixed(bool on) +{ + d->tryMixed = on; +} + } // namespace Internal } // namespace Debugger diff --git a/src/plugins/debugger/disassembleragent.h b/src/plugins/debugger/disassembleragent.h index 90f10bd2ffc..930400b3d27 100644 --- a/src/plugins/debugger/disassembleragent.h +++ b/src/plugins/debugger/disassembleragent.h @@ -45,8 +45,7 @@ class DebuggerEngine; namespace Internal { -class StackFrame; -class DisassemblerAgent; +class Location; class DisassemblerAgentPrivate; class DisassemblerAgent : public QObject @@ -58,8 +57,9 @@ public: explicit DisassemblerAgent(DebuggerEngine *engine); ~DisassemblerAgent(); - void setFrame(const StackFrame &frame, bool tryMixed, bool setMarker); - const StackFrame &frame() const; + void setTryMixed(bool on); + void setLocation(const Location &location); + const Location &location() const; void resetLocation(); void setContents(const DisassemblerLines &contents); void updateLocationMarker(); diff --git a/src/plugins/debugger/gdb/gdbengine.cpp b/src/plugins/debugger/gdb/gdbengine.cpp index a26cd9bbc6e..c45a2d13557 100644 --- a/src/plugins/debugger/gdb/gdbengine.cpp +++ b/src/plugins/debugger/gdb/gdbengine.cpp @@ -1058,7 +1058,7 @@ void GdbEngine::handleExecuteRunToLine(const GdbResponse &response) //>~"testArray () at ../simple/app.cpp:241\n" //>~"241\t s[1] = \"b\";\n" //>122^done - gotoLocation(m_targetFrame, true); + gotoLocation(m_targetFrame); showStatusMessage(tr("Target line hit. Stopped")); notifyInferiorSpontaneousStop(); handleStop1(response); @@ -1173,7 +1173,7 @@ void GdbEngine::handleStopResponse(const GdbMi &data) // Quickly set the location marker. if (lineNumber && !debuggerCore()->boolSetting(OperateByInstruction) && QFileInfo(fullName).exists()) - gotoLocation(fullName, lineNumber, true); + gotoLocation(Location(fullName, lineNumber)); if (!m_commandsToRunOnTemporaryBreak.isEmpty()) { QTC_ASSERT(state() == InferiorStopRequested, qDebug() << state()) @@ -1955,11 +1955,11 @@ void GdbEngine::executeJumpToLine(const QString &fileName, int lineNumber) // ~"run1 (argc=1, argv=0x7fffbf1f5538) at test1.cpp:242" // ~"242\t x *= 2;" // 23^done" - gotoLocation(frame, true); + gotoLocation(frame); //setBreakpoint(); //postCommand("jump " + loc); #else - gotoLocation(frame, true); + gotoLocation(frame); setBreakpoint(fileName, lineNumber); notifyInferiorRunRequested(); postCommand("jump " + loc, RunRequest); @@ -2969,7 +2969,7 @@ void GdbEngine::activateFrame(int frameIndex) handler->setCurrentIndex(frameIndex); postCommand("-stack-select-frame " + QByteArray::number(frameIndex), Discardable, CB(handleStackSelectFrame)); - gotoLocation(stackHandler()->currentFrame(), true); + gotoLocation(stackHandler()->currentFrame()); updateLocals(); reloadRegisters(); } diff --git a/src/plugins/debugger/lldb/ipcenginehost.cpp b/src/plugins/debugger/lldb/ipcenginehost.cpp index bb6f9b180d6..c5fb023cf58 100644 --- a/src/plugins/debugger/lldb/ipcenginehost.cpp +++ b/src/plugins/debugger/lldb/ipcenginehost.cpp @@ -236,7 +236,7 @@ void IPCEngineHost::selectThread(int index) void IPCEngineHost::fetchDisassembler(DisassemblerAgent *v) { - quint64 address = v->frame().address; + quint64 address = v->location().address(); m_frameToDisassemblerAgent.insert(address, v); QByteArray p; { @@ -426,7 +426,7 @@ void IPCEngineHost::rpcCallback(quint64 f, QByteArray payload) StackHandler *sh = stackHandler(); sh->setCurrentIndex(token); if (!sh->currentFrame().isUsable() || QFileInfo(sh->currentFrame().file).exists()) - gotoLocation(sh->currentFrame(), true); + gotoLocation(Location(sh->currentFrame(), true)); else if (!m_sourceAgents.contains(sh->currentFrame().file)) fetchFrameSource(token); foreach(SourceAgent *agent, m_sourceAgents.values()) diff --git a/src/plugins/debugger/pdb/pdbengine.cpp b/src/plugins/debugger/pdb/pdbengine.cpp index a993e176426..1ae2597389a 100644 --- a/src/plugins/debugger/pdb/pdbengine.cpp +++ b/src/plugins/debugger/pdb/pdbengine.cpp @@ -318,7 +318,7 @@ void PdbEngine::activateFrame(int frameIndex) //postCommand("-stack-select-frame " + QByteArray::number(frameIndex), // CB(handleStackSelectFrame)); } - gotoLocation(handler->currentFrame(), true); + gotoLocation(handler->currentFrame()); } void PdbEngine::selectThread(int index) @@ -683,7 +683,7 @@ void PdbEngine::handleResponse(const QByteArray &response0) frame.file = _(fileName); frame.line = lineNumber; if (frame.line > 0 && QFileInfo(frame.file).exists()) { - gotoLocation(frame, true); + gotoLocation(frame); notifyInferiorSpontaneousStop(); return; } @@ -797,7 +797,7 @@ void PdbEngine::handleBacktrace(const PdbResponse &response) if (currentIndex != -1) { currentIndex = frameCount - currentIndex - 1; stackHandler()->setCurrentIndex(currentIndex); - gotoLocation(stackFrames.at(currentIndex), true); + gotoLocation(stackFrames.at(currentIndex)); } updateLocals(); diff --git a/src/plugins/debugger/qml/qmlengine.cpp b/src/plugins/debugger/qml/qmlengine.cpp index c48bbeb4446..fd0e9af84fa 100644 --- a/src/plugins/debugger/qml/qmlengine.cpp +++ b/src/plugins/debugger/qml/qmlengine.cpp @@ -176,23 +176,12 @@ QmlEngine::QmlEngine(const DebuggerStartParameters &startParameters) QmlEngine::~QmlEngine() {} -void QmlEngine::gotoLocation(const QString &fileName, int lineNumber, bool setMarker) +void QmlEngine::gotoLocation(const Location &loc0) { - QString processedFilename = fileName; - + Location loc = loc0; if (isShadowBuildProject()) - processedFilename = fromShadowBuildFilename(fileName); - - DebuggerEngine::gotoLocation(processedFilename, lineNumber, setMarker); -} - -void QmlEngine::gotoLocation(const StackFrame &frame, bool setMarker) -{ - StackFrame adjustedFrame = frame; - if (isShadowBuildProject()) - adjustedFrame.file = fromShadowBuildFilename(frame.file); - - DebuggerEngine::gotoLocation(adjustedFrame, setMarker); + loc.setFileName(fromShadowBuildFilename(loc0.fileName())); + DebuggerEngine::gotoLocation(loc); } void QmlEngine::setupInferior() @@ -469,7 +458,7 @@ void QmlEngine::activateFrame(int index) << index; logMessage(LogSend, QString("%1 %2").arg(QString(cmd), QString::number(index))); sendMessage(reply); - gotoLocation(stackHandler()->frames().value(index), true); + gotoLocation(stackHandler()->frames().value(index)); } void QmlEngine::selectThread(int index) @@ -703,7 +692,7 @@ void QmlEngine::messageReceived(const QByteArray &message) for (int i = 0; i != stackFrames.size(); ++i) stackFrames[i].level = i + 1; - gotoLocation(stackFrames.value(0), true); + gotoLocation(stackFrames.value(0)); stackHandler()->setFrames(stackFrames); watchHandler()->beginCycle(); diff --git a/src/plugins/debugger/qml/qmlengine.h b/src/plugins/debugger/qml/qmlengine.h index 563e2f94652..825a5c25fd6 100644 --- a/src/plugins/debugger/qml/qmlengine.h +++ b/src/plugins/debugger/qml/qmlengine.h @@ -51,9 +51,7 @@ public: void handleRemoteSetupDone(int port); void handleRemoteSetupFailed(const QString &message); - void gotoLocation(const QString &fileName, int lineNumber, bool setMarker); - void gotoLocation(const StackFrame &frame, bool setMarker); - + void gotoLocation(const Location &location); void pauseConnection(); public slots: diff --git a/src/plugins/debugger/script/scriptengine.cpp b/src/plugins/debugger/script/scriptengine.cpp index 8b5d349964f..ab97326bf8d 100644 --- a/src/plugins/debugger/script/scriptengine.cpp +++ b/src/plugins/debugger/script/scriptengine.cpp @@ -642,11 +642,7 @@ bool ScriptEngine::checkForBreakCondition(bool byFunction) notifyInferiorSpontaneousStop(); SDEBUG("Stopped at " << lineNumber << fileName); showStatusMessage(tr("Stopped at %1:%2.").arg(fileName).arg(lineNumber), 5000); - - StackFrame frame; - frame.file = fileName; - frame.line = lineNumber; - gotoLocation(frame, true); + gotoLocation(Location(fileName, lineNumber)); updateLocals(); return true; }