summaryrefslogtreecommitdiff
path: root/src/plugins/debugger/gdb/gdbengine.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/plugins/debugger/gdb/gdbengine.cpp')
-rw-r--r--src/plugins/debugger/gdb/gdbengine.cpp120
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();