From 151b785d010b85ee0b5788f5ea95c4154d7530e0 Mon Sep 17 00:00:00 2001
From: Oswald Buddenhagen <oswald.buddenhagen@nokia.com>
Date: Fri, 30 Oct 2009 17:16:56 +0100
Subject: [PATCH] terminal adapter: make skipping of initial SIGSTOPs more
 reliable

first, _start being resolvable depends on libc-dbg being installed.
second, depending on the frame being in the dynloader makes it
a) work only for dynamic executables and b) fail on multi-target
systems (due to a hard-coded file name).
so instead just remember the entry point, as we are already there
anyway.

Reviewed-By: hjk
---
 src/plugins/debugger/gdb/gdbengine.cpp      | 22 +++++++++++++--------
 src/plugins/debugger/gdb/gdbengine.h        |  4 ++++
 src/plugins/debugger/gdb/termgdbadapter.cpp | 14 +++++++++++++
 src/plugins/debugger/gdb/termgdbadapter.h   |  3 +++
 4 files changed, 35 insertions(+), 8 deletions(-)

diff --git a/src/plugins/debugger/gdb/gdbengine.cpp b/src/plugins/debugger/gdb/gdbengine.cpp
index 2fdde0ac2a1..06d5b1f3394 100644
--- a/src/plugins/debugger/gdb/gdbengine.cpp
+++ b/src/plugins/debugger/gdb/gdbengine.cpp
@@ -285,6 +285,9 @@ void GdbEngine::initializeVariables()
     m_currentFunctionArgs.clear();
     m_currentFrame.clear();
     m_dumperHelper.clear();
+#ifdef Q_OS_LINUX
+    m_entryPoint.clear();
+#endif
 }
 
 QString GdbEngine::errorMessage(QProcess::ProcessError error)
@@ -1068,16 +1071,19 @@ void GdbEngine::handleStopResponse(const GdbMi &data)
 
 #ifdef Q_OS_LINUX
     // For some reason, attaching to a stopped process causes *two* stops
-    // when trying to continue (kernel 2.6.24-23-ubuntu).
+    // when trying to continue (kernel i386 2.6.24-23-ubuntu, gdb 6.8).
     // Interestingly enough, on MacOSX no signal is delivered at all.
-    if (reason == "signal-received"
-        && data.findChild("signal-name").data() == "SIGSTOP") {
-        GdbMi frameData = data.findChild("frame");
-        if (frameData.findChild("func").data() == "_start"
-            && frameData.findChild("from").data() == "/lib/ld-linux.so.2") {
-            continueInferiorInternal();
-            return;
+    if (!m_entryPoint.isEmpty()) {
+        if (reason == "signal-received"
+            && data.findChild("signal-name").data() == "SIGSTOP") {
+            GdbMi frameData = data.findChild("frame");
+            if (frameData.findChild("addr").data() == m_entryPoint) {
+                continueInferiorInternal();
+                return;
+            }
         }
+        // We are past the initial stops. No need to waste time on further checks.
+        m_entryPoint.clear();
     }
 #endif
 
diff --git a/src/plugins/debugger/gdb/gdbengine.h b/src/plugins/debugger/gdb/gdbengine.h
index 1229cc17d9d..2636d16c8dd 100644
--- a/src/plugins/debugger/gdb/gdbengine.h
+++ b/src/plugins/debugger/gdb/gdbengine.h
@@ -294,6 +294,10 @@ private: ////////// Inferior Management //////////
     void handleInferiorPidChanged(qint64 pid) { manager()->notifyInferiorPidChanged(pid); }
     void maybeHandleInferiorPidChanged(const QString &pid);
 
+#ifdef Q_OS_LINUX
+    QByteArray m_entryPoint;
+#endif
+
 private: ////////// View & Data Stuff //////////
 
     virtual void selectThread(int index);
diff --git a/src/plugins/debugger/gdb/termgdbadapter.cpp b/src/plugins/debugger/gdb/termgdbadapter.cpp
index e5f43eef211..b369dad4c6d 100644
--- a/src/plugins/debugger/gdb/termgdbadapter.cpp
+++ b/src/plugins/debugger/gdb/termgdbadapter.cpp
@@ -119,6 +119,9 @@ void TermGdbAdapter::handleStubAttached(const GdbResponse &response)
         setState(InferiorStopped);
         debugMessage(_("INFERIOR ATTACHED"));
         emit inferiorPrepared();
+#ifdef Q_OS_LINUX
+        m_engine->postCommand(_("-stack-list-frames 0 0"), CB(handleEntryPoint));
+#endif
     } else if (response.resultClass == GdbResultError) {
         QString msg = _(response.data.findChild("msg").data());
         emit inferiorStartFailed(msg);
@@ -130,6 +133,17 @@ void TermGdbAdapter::startInferiorPhase2()
     m_engine->continueInferiorInternal();
 }
 
+#ifdef Q_OS_LINUX
+void TermGdbAdapter::handleEntryPoint(const GdbResponse &response)
+{
+    if (response.resultClass == GdbResultDone) {
+        GdbMi stack = response.data.findChild("stack");
+        if (stack.isValid() && stack.childCount() == 1)
+            m_engine->m_entryPoint = stack.childAt(0).findChild("addr").data();
+    }
+}
+#endif
+
 void TermGdbAdapter::interruptInferior()
 {
     const qint64 attachedPID = m_engine->inferiorPid();
diff --git a/src/plugins/debugger/gdb/termgdbadapter.h b/src/plugins/debugger/gdb/termgdbadapter.h
index 11fb04a2c4c..1b98eed9874 100644
--- a/src/plugins/debugger/gdb/termgdbadapter.h
+++ b/src/plugins/debugger/gdb/termgdbadapter.h
@@ -60,6 +60,9 @@ public:
 
 private:
     void handleStubAttached(const GdbResponse &response);
+#ifdef Q_OS_LINUX
+    void handleEntryPoint(const GdbResponse &response);
+#endif
 
     Q_SLOT void handleInferiorStarted();
     Q_SLOT void stubExited();
-- 
GitLab