diff options
Diffstat (limited to 'src/plugins/debugger/gdb/gdbengine.cpp')
-rw-r--r-- | src/plugins/debugger/gdb/gdbengine.cpp | 120 |
1 files changed, 81 insertions, 39 deletions
diff --git a/src/plugins/debugger/gdb/gdbengine.cpp b/src/plugins/debugger/gdb/gdbengine.cpp index b3328cb6a1..1665061aad 100644 --- a/src/plugins/debugger/gdb/gdbengine.cpp +++ b/src/plugins/debugger/gdb/gdbengine.cpp @@ -285,6 +285,8 @@ void GdbEngine::initializeVariables() m_inbuffer.clear(); + m_commandTimer->stop(); + // ConverterState has no reset() function. m_outputCodecState.~ConverterState(); new (&m_outputCodecState) QTextCodec::ConverterState(); @@ -425,6 +427,8 @@ void GdbEngine::handleResponse(const QByteArray &buff) } if (asyncClass == "stopped") { handleStopResponse(result); + m_pendingLogStreamOutput.clear(); + m_pendingConsoleStreamOutput.clear(); } else if (asyncClass == "running") { // Archer has 'thread-id="all"' here } else if (asyncClass == "library-loaded") { @@ -1157,42 +1161,52 @@ 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) { - continueInferiorInternal(); - return; + // Due to LD_PRELOADing the dumpers, these events can occur even before + // reaching the entry point. So handle it before the entry point hacks below. + if (reason.isEmpty() && m_gdbVersion < 70000 && !m_isMacGdb) { + // On Linux it reports "Stopped due to shared library event\n", but + // on Windows it simply forgets about it. Thus, we identify the response + // based on it having no frame information. + if (!data.findChild("frame").isValid()) { + m_modulesListOutdated = m_sourcesListOutdated = true; + // Each stop causes a roundtrip and button flicker, so prevent + // a flood of useless stops. Will be automatically re-enabled. + postCommand(_("set stop-on-solib-events 0")); +#if 0 + // The related code (handleAqcuiredInferior()) is disabled as well. + if (theDebuggerBoolSetting(SelectedPluginBreakpoints)) { + QString dataStr = _(data.toString()); + debugMessage(_("SHARED LIBRARY EVENT: ") + dataStr); + QString pat = theDebuggerStringSetting(SelectedPluginBreakpointsPattern); + debugMessage(_("PATTERN: ") + pat); + postCommand(_("sharedlibrary ") + pat); + showStatusMessage(tr("Loading %1...").arg(dataStr)); } +#endif + continueInferiorInternal(); + return; } - // We are past the initial stops. No need to waste time on further checks. - m_entryPoint.clear(); } -#endif -#if 0 - // The related code (handleAqcuiredInferior()) is disabled as well. - // When re-enabling, try something to avoid spurious source list updates - // due to unrelated no-reason stops. - const QByteArray &msg = data.findChild("consolestreamoutput").data(); - if (msg.contains("Stopped due to shared library event") || reason.isEmpty()) { - m_modulesListOutdated = m_sourcesListOutdated = true; - if (theDebuggerBoolSetting(SelectedPluginBreakpoints)) { - QString dataStr = _(data.toString()); - debugMessage(_("SHARED LIBRARY EVENT: ") + dataStr); - QString pat = theDebuggerStringSetting(SelectedPluginBreakpointsPattern); - debugMessage(_("PATTERN: ") + pat); - postCommand(_("sharedlibrary ") + pat); +#ifdef Q_OS_LINUX + if (!m_entryPoint.isEmpty()) { + GdbMi frameData = data.findChild("frame"); + if (frameData.findChild("addr").data() == m_entryPoint) { + // There are two expected reasons for getting here: + // 1) For some reason, attaching to a stopped process causes *two* SIGSTOPs + // when trying to continue (kernel i386 2.6.24-23-ubuntu, gdb 6.8). + // Interestingly enough, on MacOSX no signal is delivered at all. + // 2) The explicit tbreak at the entry point we set to query the PID. + // Gdb <= 6.8 reports a frame but no reason, 6.8.50+ reports everything. + // The case of the user really setting a breakpoint at _start is simply + // unsupported. + if (!inferiorPid()) // For programs without -pthread under gdb <= 6.8. + postCommand(_("info proc"), CB(handleInfoProc)); continueInferiorInternal(); - showStatusMessage(tr("Loading %1...").arg(dataStr)); return; } - // fall through + // We are past the initial stop(s). No need to waste time on further checks. + m_entryPoint.clear(); } #endif @@ -1270,11 +1284,6 @@ void GdbEngine::handleStop1(const GdbMi &data) if (m_sourcesListOutdated) reloadSourceFilesInternal(); // This needs to be done before fullName() may need it - // Older gdb versions do not produce "library loaded" messages - // so the breakpoint update is not triggered. - if (m_gdbVersion < 70000 && !m_isMacGdb) - postCommand(_("-break-list"), CB(handleBreakList)); - QByteArray reason = data.findChild("reason").data(); if (reason == "breakpoint-hit") { showStatusMessage(tr("Stopped at breakpoint.")); @@ -1292,8 +1301,8 @@ void GdbEngine::handleStop1(const GdbMi &data) "signal from the Operating System.<p>" "<table><tr><td>Signal name : </td><td>%1</td></tr>" "<tr><td>Signal meaning : </td><td>%2</td></tr></table>") - .arg(name.isEmpty() ? tr(" <Unknown> ") : _(name)) - .arg(meaning.isEmpty() ? tr(" <Unknown> ") : _(meaning)); + .arg(name.isEmpty() ? tr(" <Unknown> ", "name") : _(name)) + .arg(meaning.isEmpty() ? tr(" <Unknown> ", "meaning") : _(meaning)); showMessageBox(QMessageBox::Information, tr("Signal received"), msg); } @@ -1337,6 +1346,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(); @@ -1399,7 +1420,6 @@ void GdbEngine::handleExecContinue(const GdbResponse &response) } else { if (state() == InferiorRunningRequested_Kill) { setState(InferiorStopped); - m_commandsToRunOnTemporaryBreak.clear(); shutdown(); return; } @@ -1416,7 +1436,6 @@ void GdbEngine::handleExecContinue(const GdbResponse &response) } else { showMessageBox(QMessageBox::Critical, tr("Execution Error"), tr("Cannot continue debugged process:\n") + QString::fromLocal8Bit(msg)); - m_commandsToRunOnTemporaryBreak.clear(); shutdown(); } } @@ -1461,6 +1480,7 @@ void GdbEngine::shutdown() // fall-through case AdapterStartFailed: // Adapter "did something", but it did not help if (m_gdbProc.state() == QProcess::Running) { + m_commandsToRunOnTemporaryBreak.clear(); postCommand(_("-gdb-exit"), GdbEngine::ExitRequest, CB(handleGdbExit)); } else { setState(DebuggerNotReady); @@ -1470,6 +1490,7 @@ void GdbEngine::shutdown() case InferiorRunning: case InferiorStopping: case InferiorStopped: + m_commandsToRunOnTemporaryBreak.clear(); postCommand(_(m_gdbAdapter->inferiorShutdownCommand()), NeedsStop | LosesChild, CB(handleInferiorShutdown)); break; @@ -1478,6 +1499,7 @@ void GdbEngine::shutdown() case InferiorShutDown: case InferiorShutdownFailed: // Whatever case InferiorUnrunnable: + m_commandsToRunOnTemporaryBreak.clear(); postCommand(_("-gdb-exit"), GdbEngine::ExitRequest, CB(handleGdbExit)); setState(EngineShuttingDown); // Do it after posting the command! break; @@ -1510,6 +1532,7 @@ void GdbEngine::handleGdbExit(const GdbResponse &response) { if (response.resultClass == GdbResultExit) { debugMessage(_("GDB CLAIMS EXIT; WAITING")); + m_commandsDoneCallback = 0; // don't set state here, this will be handled in handleGdbFinished() } else { QString msg = m_gdbAdapter->msgGdbStopFailed(_(response.data.findChild("msg").data())); @@ -2238,6 +2261,8 @@ void GdbEngine::reloadModulesInternal() { m_modulesListOutdated = false; postCommand(_("info shared"), NeedsStop, CB(handleModulesList)); + if (m_gdbVersion < 70000 && !m_isMacGdb) + postCommand(_("set stop-on-solib-events 1")); } void GdbEngine::handleModulesList(const GdbResponse &response) @@ -2278,7 +2303,7 @@ void GdbEngine::handleModulesList(const GdbResponse &response) module.symbolsRead = (item.findChild("state").data() == "Y"); module.startAddress = _(item.findChild("loaded_addr").data()); //: End address of loaded module - module.endAddress = tr("<unknown>"); + module.endAddress = tr("<unknown>", "address"); modules.append(module); } } @@ -2306,6 +2331,8 @@ void GdbEngine::reloadSourceFilesInternal() m_sourcesListOutdated = false; postCommand(_("-file-list-exec-source-files"), NeedsStop, CB(handleQuerySources)); postCommand(_("-break-list"), CB(handleBreakList)); + if (m_gdbVersion < 70000 && !m_isMacGdb) + postCommand(_("set stop-on-solib-events 1")); } @@ -4450,6 +4477,21 @@ void GdbEngine::handleAdapterStarted() void GdbEngine::handleInferiorPrepared() { + const QString qtInstallPath = m_startParameters->qtInstallPath; + if (!qtInstallPath.isEmpty()) { + QString qtBuildPath = + #if defined(Q_OS_WIN) + _("C:/qt-greenhouse/Trolltech/Code_less_create_more/Trolltech/Code_less_create_more/Troll/4.6/qt"); + #elif defined(Q_OS_MAC) + QString(); + #else + _("/var/tmp/qt-x11-src-4.6.0"); + #endif + if (!qtBuildPath.isEmpty()) + postCommand(_("set substitute-path %1 %2") + .arg(qtBuildPath).arg(qtInstallPath)); + } + // Initial attempt to set breakpoints showStatusMessage(tr("Setting breakpoints...")); attemptBreakpointSynchronization(); |