From 3dc1e31debcb166aeb57a93d393cb071a116aeb9 Mon Sep 17 00:00:00 2001
From: Oswald Buddenhagen <oswald.buddenhagen@nokia.com>
Date: Mon, 19 Oct 2009 19:04:01 +0200
Subject: [PATCH] fix initial breakpoint setting

as it turns out, it is not possible to set pending breakpoints until
gdb has loaded as image. so add some hooks to enable adapters to trigger
the initial breakpoint syncing at the right time. do not add additional
states (say, InferiorPreparing), as it would just complicate things.
---
 .../debugger/gdb/abstractgdbadapter.cpp       |  4 +++
 src/plugins/debugger/gdb/abstractgdbadapter.h |  5 ++++
 src/plugins/debugger/gdb/attachgdbadapter.cpp |  1 +
 src/plugins/debugger/gdb/gdbengine.cpp        | 25 +++++++++++++------
 src/plugins/debugger/gdb/gdbengine.h          |  4 ++-
 src/plugins/debugger/gdb/plaingdbadapter.cpp  | 10 +++++---
 src/plugins/debugger/gdb/plaingdbadapter.h    |  1 +
 src/plugins/debugger/gdb/remotegdbadapter.cpp |  7 +++++-
 src/plugins/debugger/gdb/remotegdbadapter.h   |  1 +
 src/plugins/debugger/gdb/trkgdbadapter.cpp    |  9 +++++--
 src/plugins/debugger/gdb/trkgdbadapter.h      |  1 +
 11 files changed, 53 insertions(+), 15 deletions(-)

diff --git a/src/plugins/debugger/gdb/abstractgdbadapter.cpp b/src/plugins/debugger/gdb/abstractgdbadapter.cpp
index cd99fec311e..dca2e9ad5be 100644
--- a/src/plugins/debugger/gdb/abstractgdbadapter.cpp
+++ b/src/plugins/debugger/gdb/abstractgdbadapter.cpp
@@ -51,6 +51,10 @@ void AbstractGdbAdapter::shutdown()
 {
 }
 
+void AbstractGdbAdapter::startInferiorPhase2()
+{
+}
+
 const char *AbstractGdbAdapter::inferiorShutdownCommand() const
 {
     return "kill";
diff --git a/src/plugins/debugger/gdb/abstractgdbadapter.h b/src/plugins/debugger/gdb/abstractgdbadapter.h
index 9dc018e0380..7fed63fc8c3 100644
--- a/src/plugins/debugger/gdb/abstractgdbadapter.h
+++ b/src/plugins/debugger/gdb/abstractgdbadapter.h
@@ -56,6 +56,7 @@ public:
 
     virtual void startAdapter() = 0;
     virtual void startInferior() = 0;
+    virtual void startInferiorPhase2();
     virtual void interruptInferior() = 0;
     virtual void shutdown();
     virtual const char *inferiorShutdownCommand() const;
@@ -80,6 +81,10 @@ signals:
     // Make sure to clean up everything before emitting this signal.
     void adapterCrashed(const QString &msg);
 
+    // This triggers the initial breakpoint synchronization and causes
+    // startInferiorPhase2() being called once done.
+    void inferiorPrepared();
+
     // The adapter is still running just fine, but it failed to acquire a debuggee.
     void inferiorStartFailed(const QString &msg);
     
diff --git a/src/plugins/debugger/gdb/attachgdbadapter.cpp b/src/plugins/debugger/gdb/attachgdbadapter.cpp
index f89421e5929..ae83ed6a490 100644
--- a/src/plugins/debugger/gdb/attachgdbadapter.cpp
+++ b/src/plugins/debugger/gdb/attachgdbadapter.cpp
@@ -82,6 +82,7 @@ void AttachGdbAdapter::handleAttach(const GdbResponse &response)
         QTC_ASSERT(state() == InferiorStopped, qDebug() << state());
         debugMessage(_("INFERIOR ATTACHED"));
         showStatusMessage(msgAttachedToStoppedInferior());
+        emit inferiorPrepared();
         m_engine->updateAll();
     } else {
         QString msg = __(response.data.findChild("msg").data());
diff --git a/src/plugins/debugger/gdb/gdbengine.cpp b/src/plugins/debugger/gdb/gdbengine.cpp
index 93916267abb..87024f56ea7 100644
--- a/src/plugins/debugger/gdb/gdbengine.cpp
+++ b/src/plugins/debugger/gdb/gdbengine.cpp
@@ -234,6 +234,9 @@ void GdbEngine::connectAdapter()
     connect(m_gdbAdapter, SIGNAL(adapterStartFailed(QString,QString)),
         this, SLOT(handleAdapterStartFailed(QString,QString)));
 
+    connect(m_gdbAdapter, SIGNAL(inferiorPrepared()),
+        this, SLOT(handleInferiorPrepared()));
+
     connect(m_gdbAdapter, SIGNAL(inferiorStartFailed(QString)),
         this, SLOT(handleInferiorStartFailed(QString)));
 
@@ -692,7 +695,8 @@ void GdbEngine::postCommandHelper(const GdbCommand &cmd)
     }
 
     if (cmd.flags & NeedsStop) {
-        if (state() == InferiorStopped || state() == AdapterStarted) {
+        if (state() == InferiorStopped
+            || state() == InferiorStarting || state() == AdapterStarted) {
             // Can be safely sent now.
             flushCommand(cmd);
         } else {
@@ -4318,24 +4322,29 @@ void GdbEngine::handleAdapterStarted()
     setState(AdapterStarted);
     debugMessage(_("ADAPTER SUCCESSFULLY STARTED"));
 
+    showStatusMessage(tr("Starting inferior..."));
+    setState(InferiorStarting);
+    m_gdbAdapter->startInferior();
+}
+
+void GdbEngine::handleInferiorPrepared()
+{
     // Initial attempt to set breakpoints
     showStatusMessage(tr("Setting breakpoints..."));
     attemptBreakpointSynchronization();
 
     if (m_cookieForToken.isEmpty()) {
-        startInferior();
+        startInferiorPhase2();
     } else {
         QTC_ASSERT(m_commandsDoneCallback == 0, /**/);
-        m_commandsDoneCallback = &GdbEngine::startInferior;
+        m_commandsDoneCallback = &GdbEngine::startInferiorPhase2;
     }
 }
 
-void GdbEngine::startInferior()
+void GdbEngine::startInferiorPhase2()
 {
-    QTC_ASSERT(state() == AdapterStarted, qDebug() << state());
-    showStatusMessage(tr("Starting inferior..."));
-    setState(InferiorStarting);
-    m_gdbAdapter->startInferior();
+    debugMessage(_("BREAKPOINTS SET, CONTINUING INFERIOR STARTUP"));
+    m_gdbAdapter->startInferiorPhase2();
 }
 
 void GdbEngine::handleInferiorStartFailed(const QString &msg)
diff --git a/src/plugins/debugger/gdb/gdbengine.h b/src/plugins/debugger/gdb/gdbengine.h
index 91c230dacc9..94e91e4669a 100644
--- a/src/plugins/debugger/gdb/gdbengine.h
+++ b/src/plugins/debugger/gdb/gdbengine.h
@@ -126,7 +126,7 @@ private: ////////// Gdb Process Management //////////
     AbstractGdbAdapter *createAdapter(const DebuggerStartParametersPtr &dp);
     void connectAdapter();
     bool startGdb(const QStringList &args = QStringList(), const QString &gdb = QString());
-    void startInferior();
+    void startInferiorPhase2();
 
     void handleInferiorShutdown(const GdbResponse &response);
     void handleGdbExit(const GdbResponse &response);
@@ -146,6 +146,8 @@ private slots:
     void handleAdapterStarted();
     void handleAdapterStartFailed(const QString &msg, const QString &settingsIdHint = QString());
 
+    void handleInferiorPrepared();
+
     void handleInferiorStartFailed(const QString &msg);
 
     void handleAdapterCrashed(const QString &msg);
diff --git a/src/plugins/debugger/gdb/plaingdbadapter.cpp b/src/plugins/debugger/gdb/plaingdbadapter.cpp
index 2a16c27628f..8df6d740165 100644
--- a/src/plugins/debugger/gdb/plaingdbadapter.cpp
+++ b/src/plugins/debugger/gdb/plaingdbadapter.cpp
@@ -106,9 +106,7 @@ void PlainGdbAdapter::handleFileExecAndSymbols(const GdbResponse &response)
 {
     QTC_ASSERT(state() == InferiorStarting, qDebug() << state());
     if (response.resultClass == GdbResultDone) {
-        //m_breakHandler->clearBreakMarkers();
-        setState(InferiorRunningRequested);
-        m_engine->postCommand(_("-exec-run"), GdbEngine::RunRequest, CB(handleExecRun));
+        emit inferiorPrepared();
     } else {
         QString msg = tr("Starting executable failed:\n") +
             __(response.data.findChild("msg").data());
@@ -116,6 +114,12 @@ void PlainGdbAdapter::handleFileExecAndSymbols(const GdbResponse &response)
     }
 }
 
+void PlainGdbAdapter::startInferiorPhase2()
+{
+    setState(InferiorRunningRequested);
+    m_engine->postCommand(_("-exec-run"), GdbEngine::RunRequest, CB(handleExecRun));
+}
+
 void PlainGdbAdapter::handleExecRun(const GdbResponse &response)
 {
     if (response.resultClass == GdbResultRunning) {
diff --git a/src/plugins/debugger/gdb/plaingdbadapter.h b/src/plugins/debugger/gdb/plaingdbadapter.h
index fb445d3b329..0998ad2b82f 100644
--- a/src/plugins/debugger/gdb/plaingdbadapter.h
+++ b/src/plugins/debugger/gdb/plaingdbadapter.h
@@ -57,6 +57,7 @@ public:
 
     void startAdapter();
     void startInferior();
+    void startInferiorPhase2();
     void interruptInferior();
     void shutdown();
     const char *inferiorShutdownCommand() const { return "kill"; }
diff --git a/src/plugins/debugger/gdb/remotegdbadapter.cpp b/src/plugins/debugger/gdb/remotegdbadapter.cpp
index 504e0a56208..ab06baab433 100644
--- a/src/plugins/debugger/gdb/remotegdbadapter.cpp
+++ b/src/plugins/debugger/gdb/remotegdbadapter.cpp
@@ -199,7 +199,7 @@ void RemoteGdbAdapter::handleTargetRemote(const GdbResponse &record)
         // gdb server will stop the remote application itself.
         debugMessage(_("INFERIOR STARTED"));
         showStatusMessage(msgAttachedToStoppedInferior());
-        m_engine->continueInferior();
+        emit inferiorPrepared();
     } else {
         // 16^error,msg="hd:5555: Connection timed out."
         QString msg = msgConnectRemoteServerFailed(__(record.data.findChild("msg").data()));
@@ -207,6 +207,11 @@ void RemoteGdbAdapter::handleTargetRemote(const GdbResponse &record)
     }
 }
 
+void RemoteGdbAdapter::startInferiorPhase2()
+{
+    m_engine->continueInferior();
+}
+
 void RemoteGdbAdapter::interruptInferior()
 {
     m_engine->postCommand(_("-exec-interrupt"));
diff --git a/src/plugins/debugger/gdb/remotegdbadapter.h b/src/plugins/debugger/gdb/remotegdbadapter.h
index a7f4bc645a4..edc65ece950 100644
--- a/src/plugins/debugger/gdb/remotegdbadapter.h
+++ b/src/plugins/debugger/gdb/remotegdbadapter.h
@@ -56,6 +56,7 @@ public:
 
     void startAdapter();
     void startInferior();
+    void startInferiorPhase2();
     void interruptInferior();
     void shutdown();
 
diff --git a/src/plugins/debugger/gdb/trkgdbadapter.cpp b/src/plugins/debugger/gdb/trkgdbadapter.cpp
index e1405d86f42..d41ff232733 100644
--- a/src/plugins/debugger/gdb/trkgdbadapter.cpp
+++ b/src/plugins/debugger/gdb/trkgdbadapter.cpp
@@ -1639,8 +1639,7 @@ void TrkGdbAdapter::handleTargetRemote(const GdbResponse &record)
 {
     QTC_ASSERT(state() == InferiorStarting, qDebug() << state());
     if (record.resultClass == GdbResultDone) {
-        setState(InferiorRunningRequested);
-        m_engine->postCommand(_("-exec-continue"), GdbEngine::RunRequest, CB(handleFirstContinue));
+        emit inferiorPrepared();
     } else {
         QString msg = tr("Connecting to trk server adapter failed:\n")
             + _(record.data.findChild("msg").data());
@@ -1648,6 +1647,12 @@ void TrkGdbAdapter::handleTargetRemote(const GdbResponse &record)
     }
 }
 
+void TrkGdbAdapter::startInferiorPhase2()
+{
+    setState(InferiorRunningRequested);
+    m_engine->postCommand(_("-exec-continue"), GdbEngine::RunRequest, CB(handleFirstContinue));
+}
+
 void TrkGdbAdapter::handleFirstContinue(const GdbResponse &record)
 {
     QTC_ASSERT(state() == InferiorRunning, qDebug() << state());
diff --git a/src/plugins/debugger/gdb/trkgdbadapter.h b/src/plugins/debugger/gdb/trkgdbadapter.h
index 72a996ef01f..42d8911401f 100644
--- a/src/plugins/debugger/gdb/trkgdbadapter.h
+++ b/src/plugins/debugger/gdb/trkgdbadapter.h
@@ -170,6 +170,7 @@ public:
 private:
     void startAdapter();
     void startInferior();
+    void startInferiorPhase2();
     void interruptInferior();
     void shutdown();
 
-- 
GitLab