diff --git a/src/plugins/debugger/gdb/gdbengine.cpp b/src/plugins/debugger/gdb/gdbengine.cpp index b7e231434b5d75bb716318d7121b998df825fd26..47a4de1f8781f7d7978b765d967857d004758753 100644 --- a/src/plugins/debugger/gdb/gdbengine.cpp +++ b/src/plugins/debugger/gdb/gdbengine.cpp @@ -1152,14 +1152,21 @@ void GdbEngine::handleStopResponse(const GdbMi &data) setState(InferiorStopped); #ifdef Q_OS_LINUX - // For some reason, attaching to a stopped process causes *two* stops - // 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 (!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) { + GdbMi frameData = data.findChild("frame"); + if (frameData.findChild("addr").data() == m_entryPoint) { + if (reason == "signal-received" + && data.findChild("signal-name").data() == "SIGSTOP") { + // For some reason, attaching to a stopped process causes *two* stops + // when trying to continue (kernel i386 2.6.24-23-ubuntu, gdb 6.8). + // Interestingly enough, on MacOSX no signal is delivered at all. + continueInferiorInternal(); + return; + } + if (reason.isEmpty()) { // tbreak does that + // For programs without -pthread under gdb <= 6.8. + if (!inferiorPid()) + postCommand(_("info proc"), CB(handleInfoProc)); continueInferiorInternal(); return; } @@ -1325,6 +1332,18 @@ void GdbEngine::handleStop1(const GdbMi &data) manager()->reloadRegisters(); } +#ifdef Q_OS_LINUX +void GdbEngine::handleInfoProc(const GdbResponse &response) +{ + if (response.resultClass == GdbResultDone) { + static QRegExp re(_("\\bprocess ([0-9]+)\n")); + QTC_ASSERT(re.isValid(), return); + if (re.indexIn(_(response.data.findChild("consolestreamoutput").data())) != -1) + maybeHandleInferiorPidChanged(re.cap(1)); + } +} +#endif + void GdbEngine::handleShowVersion(const GdbResponse &response) { //qDebug () << "VERSION 2:" << response.data.findChild("consolestreamoutput").data(); diff --git a/src/plugins/debugger/gdb/gdbengine.h b/src/plugins/debugger/gdb/gdbengine.h index aafe05b96e08e22b62dcf101bc86ab9e61f386f9..dc1acf68fcc3feb27b3a642d0a8eca215b499d16 100644 --- a/src/plugins/debugger/gdb/gdbengine.h +++ b/src/plugins/debugger/gdb/gdbengine.h @@ -302,6 +302,8 @@ private: ////////// Inferior Management ////////// void maybeHandleInferiorPidChanged(const QString &pid); #ifdef Q_OS_LINUX + void handleInfoProc(const GdbResponse &response); + QByteArray m_entryPoint; #endif diff --git a/src/plugins/debugger/gdb/plaingdbadapter.cpp b/src/plugins/debugger/gdb/plaingdbadapter.cpp index 9f0d4c0e832e62e5cf82602f693d057cfd815651..fbcf96c860530d3a2c662e25b8ce144ab0eaeb39 100644 --- a/src/plugins/debugger/gdb/plaingdbadapter.cpp +++ b/src/plugins/debugger/gdb/plaingdbadapter.cpp @@ -110,6 +110,13 @@ void PlainGdbAdapter::handleFileExecAndSymbols(const GdbResponse &response) { QTC_ASSERT(state() == InferiorStarting, qDebug() << state()); if (response.resultClass == GdbResultDone) { +#ifdef Q_OS_LINUX + // Old gdbs do not announce the PID for programs without pthreads. + // Note that successfully preloading the debugging helpers will + // automatically load pthreads, so this will be unnecessary. + if (m_engine->m_gdbVersion < 70000) + m_engine->postCommand(_("info target"), CB(handleInfoTarget)); +#endif emit inferiorPrepared(); } else { QString msg = tr("Starting executable failed:\n") + @@ -118,6 +125,29 @@ void PlainGdbAdapter::handleFileExecAndSymbols(const GdbResponse &response) } } +#ifdef Q_OS_LINUX +void PlainGdbAdapter::handleInfoTarget(const GdbResponse &response) +{ + if (response.resultClass == GdbResultDone) { + // [some leading stdout here] + // >&" Entry point: 0x80831f0 0x08048134 - 0x08048147 is .interp\n" + // [some trailing stdout here] + QString msg = _(response.data.findChild("consolestreamoutput").data()); + QRegExp needle(_("\\bEntry point: 0x([0-9a-f]+)\\b")); + if (needle.indexIn(msg) != -1) { + m_engine->m_entryPoint = + "0x" + needle.cap(1).toLatin1().rightJustified(sizeof(void *) * 2, '0'); + m_engine->postCommand(_("tbreak *0x") + needle.cap(1)); + // Do nothing here - inferiorPrepared handles the sequencing. + } else { + emit inferiorStartFailed(_("Parsing start address failed")); + } + } else if (response.resultClass == GdbResultError) { + emit inferiorStartFailed(_("Fetching start address failed")); + } +} +#endif + void PlainGdbAdapter::startInferiorPhase2() { setState(InferiorRunningRequested); diff --git a/src/plugins/debugger/gdb/plaingdbadapter.h b/src/plugins/debugger/gdb/plaingdbadapter.h index 21545212af73e49ccac7ffaf350eb9087ae88d82..2a60a86643a126a965da88e8de094e8ce25c8ee1 100644 --- a/src/plugins/debugger/gdb/plaingdbadapter.h +++ b/src/plugins/debugger/gdb/plaingdbadapter.h @@ -62,6 +62,9 @@ public: private: void handleFileExecAndSymbols(const GdbResponse &response); void handleExecRun(const GdbResponse &response); +#ifdef Q_OS_LINUX + void handleInfoTarget(const GdbResponse &response); +#endif OutputCollector m_outputCollector; };