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); }