diff --git a/src/plugins/debugger/cdb/cdbdebugengine.cpp b/src/plugins/debugger/cdb/cdbdebugengine.cpp index b5c8c26086d5458b1ef5a7eea9ab0e215a90716e..14b22a6dc519a536e77bdab5dc62d481aeb472c6 100644 --- a/src/plugins/debugger/cdb/cdbdebugengine.cpp +++ b/src/plugins/debugger/cdb/cdbdebugengine.cpp @@ -1084,9 +1084,9 @@ bool CdbDebugEnginePrivate::attemptBreakpointSynchronization(QString *errorMessa return ok; } -void CdbDebugEngine::fetchDisassembler(DisassemblerViewAgent *agent, - const StackFrame & frame) +void CdbDebugEngine::fetchDisassembler(DisassemblerViewAgent *agent) { + StackFrame frame = agent->frame(); enum { ContextLines = 40 }; bool ok = false; QString errorMessage; diff --git a/src/plugins/debugger/cdb/cdbdebugengine.h b/src/plugins/debugger/cdb/cdbdebugengine.h index 0f900560d0c2ede5ebbcf062acae390f36112e70..1085a71de75dd17e19e0e2d36d133f42560168a2 100644 --- a/src/plugins/debugger/cdb/cdbdebugengine.h +++ b/src/plugins/debugger/cdb/cdbdebugengine.h @@ -88,8 +88,7 @@ public: virtual void attemptBreakpointSynchronization(); - virtual void fetchDisassembler(DisassemblerViewAgent *agent, - const StackFrame &frame); + virtual void fetchDisassembler(DisassemblerViewAgent *agent); virtual void fetchMemory(MemoryViewAgent *, quint64 addr, quint64 length); virtual void reloadModules(); diff --git a/src/plugins/debugger/debuggeragents.cpp b/src/plugins/debugger/debuggeragents.cpp index 820b48c9498739e8c5b1de1529ef459a4caf24d3..d76b6f386bf19022b7d2c154e488ddcc1a94f565 100644 --- a/src/plugins/debugger/debuggeragents.cpp +++ b/src/plugins/debugger/debuggeragents.cpp @@ -153,8 +153,11 @@ public: struct DisassemblerViewAgentPrivate { + DisassemblerViewAgentPrivate() { tryMixed = true; } + QPointer<TextEditor::ITextEditor> editor; StackFrame frame; + bool tryMixed; QPointer<DebuggerManager> manager; LocationMark2 *locationMark; QHash<QString, QString> cache; @@ -230,10 +233,24 @@ QString frameKey(const StackFrame &frame) return _("%1:%2:%3").arg(frame.function).arg(frame.file).arg(frame.from); } -void DisassemblerViewAgent::setFrame(const StackFrame &frame) +const StackFrame &DisassemblerViewAgent::frame() const +{ + return d->frame; +} + +bool DisassemblerViewAgent::isMixed() const +{ + return d->tryMixed + && d->frame.line > 0 + && !d->frame.function.isEmpty() + && d->frame.function != _("??"); +} + +void DisassemblerViewAgent::setFrame(const StackFrame &frame, bool tryMixed) { d->frame = frame; - if (!frame.function.isEmpty() && frame.function != _("??")) { + d->tryMixed = tryMixed; + if (isMixed()) { QHash<QString, QString>::ConstIterator it = d->cache.find(frameKey(frame)); if (it != d->cache.end()) { QString msg = _("Use cache disassembler for '%1' in '%2'") @@ -245,7 +262,7 @@ void DisassemblerViewAgent::setFrame(const StackFrame &frame) } IDebuggerEngine *engine = d->manager->currentEngine(); QTC_ASSERT(engine, return); - engine->fetchDisassembler(this, frame); + engine->fetchDisassembler(this); } void DisassemblerViewAgent::setContents(const QString &contents) diff --git a/src/plugins/debugger/debuggeragents.h b/src/plugins/debugger/debuggeragents.h index f0888c6b92f8730b24606d741fd290fea224c90a..63d3e7ba238f29083efcca36f6e21bdcbf5c5dd3 100644 --- a/src/plugins/debugger/debuggeragents.h +++ b/src/plugins/debugger/debuggeragents.h @@ -83,12 +83,14 @@ public: explicit DisassemblerViewAgent(DebuggerManager *manager); ~DisassemblerViewAgent(); - void setFrame(const StackFrame &frame); + void setFrame(const StackFrame &frame, bool tryMixed = true); + const StackFrame &frame() const; void resetLocation(); Q_SLOT void setContents(const QString &contents); QString address() const; bool contentsCoversAddress(const QString &contents) const; void cleanup(); + bool isMixed() const; private: DisassemblerViewAgentPrivate *d; diff --git a/src/plugins/debugger/gdb/gdbengine.cpp b/src/plugins/debugger/gdb/gdbengine.cpp index 355ff71b88772cc6712a9eb181105a8bdbfb9355..ee415d667e5ac0e195bab5df68f02427cb6db409 100644 --- a/src/plugins/debugger/gdb/gdbengine.cpp +++ b/src/plugins/debugger/gdb/gdbengine.cpp @@ -1727,9 +1727,35 @@ void GdbEngine::stepExec() setState(InferiorRunningRequested); showStatusMessage(tr("Step requested..."), 5000); if (manager()->isReverseDebugging()) - postCommand("-reverse-step", RunRequest, CB(handleExecContinue)); + postCommand("-reverse-step", RunRequest, CB(handleExecStep)); else - postCommand("-exec-step", RunRequest, CB(handleExecContinue)); + postCommand("-exec-step", RunRequest, CB(handleExecStep)); +} + +void GdbEngine::handleExecStep(const GdbResponse &response) +{ + if (response.resultClass == GdbResultRunning) { + // The "running" state is picked up in handleResponse() + QTC_ASSERT(state() == InferiorRunning, /**/); + } else { + if (state() == InferiorRunningRequested_Kill) { + setState(InferiorStopped); + shutdown(); + return; + } + QTC_ASSERT(state() == InferiorRunningRequested, /**/); + setState(InferiorStopped); + QByteArray msg = response.data.findChild("msg").data(); + if (msg.startsWith("Cannot find bounds of current function")) { + if (!m_commandsToRunOnTemporaryBreak.isEmpty()) + flushQueuedCommands(); + stepIExec(); // Fall back to instruction-wise stepping. + } else { + showMessageBox(QMessageBox::Critical, tr("Execution Error"), + tr("Cannot continue debugged process:\n") + QString::fromLocal8Bit(msg)); + shutdown(); + } + } } void GdbEngine::stepIExec() @@ -1760,9 +1786,35 @@ void GdbEngine::nextExec() setState(InferiorRunningRequested); showStatusMessage(tr("Step next requested..."), 5000); if (manager()->isReverseDebugging()) - postCommand("-reverse-next", RunRequest, CB(handleExecContinue)); + postCommand("-reverse-next", RunRequest, CB(handleExecNext)); else - postCommand("-exec-next", RunRequest, CB(handleExecContinue)); + postCommand("-exec-next", RunRequest, CB(handleExecNext)); +} + +void GdbEngine::handleExecNext(const GdbResponse &response) +{ + if (response.resultClass == GdbResultRunning) { + // The "running" state is picked up in handleResponse() + QTC_ASSERT(state() == InferiorRunning, /**/); + } else { + if (state() == InferiorRunningRequested_Kill) { + setState(InferiorStopped); + shutdown(); + return; + } + QTC_ASSERT(state() == InferiorRunningRequested, /**/); + setState(InferiorStopped); + QByteArray msg = response.data.findChild("msg").data(); + if (msg.startsWith("Cannot find bounds of current function")) { + if (!m_commandsToRunOnTemporaryBreak.isEmpty()) + flushQueuedCommands(); + nextIExec(); // Fall back to instruction-wise stepping. + } else { + showMessageBox(QMessageBox::Critical, tr("Execution Error"), + tr("Cannot continue debugged process:\n") + QString::fromLocal8Bit(msg)); + shutdown(); + } + } } void GdbEngine::nextIExec() @@ -3405,18 +3457,20 @@ struct DisassemblerAgentCookie QPointer<DisassemblerViewAgent> agent; }; -void GdbEngine::fetchDisassembler(DisassemblerViewAgent *agent, - const StackFrame &frame) + +// FIXME: add agent->frame() accessor and use that +void GdbEngine::fetchDisassembler(DisassemblerViewAgent *agent) { - if (frame.file.isEmpty()) { - fetchDisassemblerByAddress(agent, true); - } else { + if (agent->isMixed()) { // Disassemble full function: + const StackFrame &frame = agent->frame(); QByteArray cmd = "-data-disassemble" " -f " + frame.file.toLocal8Bit() + " -l " + QByteArray::number(frame.line) + " -n -1 -- 1"; postCommand(cmd, Discardable, CB(handleFetchDisassemblerByLine), QVariant::fromValue(DisassemblerAgentCookie(agent))); + } else { + fetchDisassemblerByAddress(agent, true); } } diff --git a/src/plugins/debugger/gdb/gdbengine.h b/src/plugins/debugger/gdb/gdbengine.h index 6fd2c5e2cf10478f668f0442f717a7cc14656671..df6e9df97f07690ee87ef94c3e56096b6999c1eb 100644 --- a/src/plugins/debugger/gdb/gdbengine.h +++ b/src/plugins/debugger/gdb/gdbengine.h @@ -300,6 +300,8 @@ private: ////////// Inferior Management ////////// virtual void jumpToLineExec(const QString &fileName, int lineNumber); void handleExecContinue(const GdbResponse &response); + void handleExecStep(const GdbResponse &response); + void handleExecNext(const GdbResponse &response); qint64 inferiorPid() const { return m_manager->inferiorPid(); } void handleInferiorPidChanged(qint64 pid) { manager()->notifyInferiorPidChanged(pid); } @@ -357,8 +359,7 @@ private: ////////// View & Data Stuff ////////// // // Disassembler specific stuff // - virtual void fetchDisassembler(DisassemblerViewAgent *agent, - const StackFrame &frame); + virtual void fetchDisassembler(DisassemblerViewAgent *agent); void fetchDisassemblerByAddress(DisassemblerViewAgent *agent, bool useMixedMode); void handleFetchDisassemblerByLine(const GdbResponse &response); diff --git a/src/plugins/debugger/idebuggerengine.h b/src/plugins/debugger/idebuggerengine.h index 2c72aa845b4109454ea8c8b673a43fd73ee4ab0e..6733971d2d59e96890b1fd1914afabf585dde98a 100644 --- a/src/plugins/debugger/idebuggerengine.h +++ b/src/plugins/debugger/idebuggerengine.h @@ -56,7 +56,6 @@ namespace Internal { class DisassemblerViewAgent; class MemoryViewAgent; -struct StackFrame; class Symbol; class WatchData; @@ -111,7 +110,7 @@ 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 &) {} + virtual void fetchDisassembler(DisassemblerViewAgent *) {} virtual void setRegisterValue(int regnr, const QString &value) { Q_UNUSED(regnr); Q_UNUSED(value); }