diff --git a/src/plugins/debugger/debuggeractions.cpp b/src/plugins/debugger/debuggeractions.cpp index 5fac7cbcc03..aa480a067df 100644 --- a/src/plugins/debugger/debuggeractions.cpp +++ b/src/plugins/debugger/debuggeractions.cpp @@ -415,6 +415,12 @@ DebuggerSettings::DebuggerSettings(QSettings *settings) item->setDefaultValue(false); insertItem(AutoQuit, item); + item = new SavedAction(this); + item->setSettingsKey(debugModeGroup, QLatin1String("AttemptQuickStart")); + item->setCheckable(true); + item->setDefaultValue(false); + insertItem(AttemptQuickStart, item); + item = new SavedAction(this); item->setSettingsKey(debugModeGroup, QLatin1String("UseToolTips")); item->setText(tr("Use tooltips in main editor when debugging")); diff --git a/src/plugins/debugger/debuggeractions.h b/src/plugins/debugger/debuggeractions.h index 9da4ab1b051..1082ae8f2c5 100644 --- a/src/plugins/debugger/debuggeractions.h +++ b/src/plugins/debugger/debuggeractions.h @@ -118,6 +118,7 @@ enum DebuggerActionCode // Gdb LoadGdbInit, + AttemptQuickStart, GdbStartupCommands, GdbWatchdogTimeout, AutoEnrichParameters, diff --git a/src/plugins/debugger/gdb/attachgdbadapter.cpp b/src/plugins/debugger/gdb/attachgdbadapter.cpp index 28c722a4e08..98e35c4b9b7 100644 --- a/src/plugins/debugger/gdb/attachgdbadapter.cpp +++ b/src/plugins/debugger/gdb/attachgdbadapter.cpp @@ -86,7 +86,7 @@ void AttachGdbAdapter::runEngine() .arg(m_engine->inferiorPid())); m_engine->notifyEngineRunAndInferiorStopOk(); GdbMi data; - m_engine->handleStop0(data); + m_engine->handleStop1(data); } void AttachGdbAdapter::handleAttach(const GdbResponse &response) diff --git a/src/plugins/debugger/gdb/gdbengine.cpp b/src/plugins/debugger/gdb/gdbengine.cpp index 966e5fd0422..52e8bb79403 100644 --- a/src/plugins/debugger/gdb/gdbengine.cpp +++ b/src/plugins/debugger/gdb/gdbengine.cpp @@ -262,6 +262,7 @@ GdbEngine::GdbEngine(const DebuggerStartParameters &startParameters, m_preparedForQmlBreak = false; m_disassembleUsesComma = false; m_actingOnExpectedStop = false; + m_fullStartDone = false; invalidateSourcesList(); @@ -1290,7 +1291,7 @@ void GdbEngine::handleExecuteJumpToLine(const GdbResponse &response) // This happens on old gdb. Trigger the effect of a '*stopped'. showStatusMessage(tr("Jumped. Stopped")); notifyInferiorSpontaneousStop(); - handleStop1(response); + handleStop2(response); } } @@ -1388,6 +1389,15 @@ void GdbEngine::handleStopResponse(const GdbMi &data) return; } + bool gotoHandleStop1 = true; + if (!m_fullStartDone) { + m_fullStartDone = true; + postCommand("sharedlibrary .*"); + loadPythonDumpers(); + postCommand("p 3", CB(handleStop1)); + gotoHandleStop1 = false; + } + BreakpointResponseId rid(data.findChild("bkptno").data()); const GdbMi frame = data.findChild("frame"); @@ -1467,7 +1477,8 @@ void GdbEngine::handleStopResponse(const GdbMi &data) if (isQmlStepBreakpoint1(rid)) return; - handleStop0(data); + if (gotoHandleStop1) + handleStop1(data); } static QByteArray stopSignal(Abi abi) @@ -1475,37 +1486,13 @@ static QByteArray stopSignal(Abi abi) return (abi.os() == Abi::WindowsOS) ? QByteArray("SIGTRAP") : QByteArray("SIGINT"); } -void GdbEngine::handleStop0(const GdbMi &data) +void GdbEngine::handleStop1(const GdbResponse &response) { -#if 0 // See http://vladimir_prus.blogspot.com/2007/12/debugger-stories-pending-breakpoints.html - // 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()) { - invalidateSourcesList(); - // 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 (debuggerCore()->boolSetting(SelectedPluginBreakpoints)) { - QString dataStr = _(data.toString()); - showMessage(_("SHARED LIBRARY EVENT: ") + dataStr); - QString pat = theDebuggerStringSetting(SelectedPluginBreakpointsPattern); - showMessage(_("PATTERN: ") + pat); - postCommand("sharedlibrary " + pat.toLocal8Bit()); - showStatusMessage(tr("Loading %1...").arg(dataStr)); - } -#endif - continueInferiorInternal(); - return; - } - } -#endif + handleStop1(response.cookie.value()); +} +void GdbEngine::handleStop1(const GdbMi &data) +{ const GdbMi frame = data.findChild("frame"); const QByteArray reason = data.findChild("reason").data(); @@ -1580,20 +1567,20 @@ void GdbEngine::handleStop0(const GdbMi &data) if (initHelpers) { tryLoadDebuggingHelpersClassic(); QVariant var = QVariant::fromValue(data); - postCommand("p 4", CB(handleStop1), var); // dummy + postCommand("p 4", CB(handleStop2), var); // dummy } else { - handleStop1(data); + handleStop2(data); } // Dumper loading is sequenced, as otherwise the display functions // will start requesting data without knowing that dumpers are available. } -void GdbEngine::handleStop1(const GdbResponse &response) +void GdbEngine::handleStop2(const GdbResponse &response) { - handleStop1(response.cookie.value()); + handleStop2(response.cookie.value()); } -void GdbEngine::handleStop1(const GdbMi &data) +void GdbEngine::handleStop2(const GdbMi &data) { if (isDying()) { qDebug() << "HANDLING STOP WHILE DYING"; @@ -2592,7 +2579,7 @@ QByteArray GdbEngine::breakpointLocation(BreakpointModelId id) return (abi.os() == Abi::WindowsOS) ? "qMain" : "main"; } if (data.type == BreakpointByFunction) - return data.functionName.toUtf8(); + return '"' + data.functionName.toUtf8() + '"'; if (data.type == BreakpointByAddress) return addressSpec(data.address); @@ -4814,7 +4801,7 @@ bool GdbEngine::startGdb(const QStringList &args, const QString &settingsIdHint) showMessage(_("GDB STARTED, INITIALIZING IT")); postCommand("show version", CB(handleShowVersion)); - postCommand("-list-features", CB(handleListFeatures)); + //postCommand("-list-features", CB(handleListFeatures)); //postCommand("-enable-timings"); //postCommand("set print static-members off"); // Seemingly doesn't work. @@ -4837,6 +4824,7 @@ bool GdbEngine::startGdb(const QStringList &args, const QString &settingsIdHint) postCommand("set breakpoint pending on"); postCommand("set print elements 10000"); + // Produces a few messages during symtab loading //postCommand("set verbose on"); @@ -4873,7 +4861,7 @@ bool GdbEngine::startGdb(const QStringList &args, const QString &settingsIdHint) // displaced-stepping does not work in Thumb mode. //postCommand("set displaced-stepping on"); postCommand("set trust-readonly-sections on", ConsoleCommand); - postCommand("set auto-solib-add on", ConsoleCommand); + postCommand("set remotecache on", ConsoleCommand); //postCommand("set non-stop on", ConsoleCommand); @@ -4889,7 +4877,13 @@ bool GdbEngine::startGdb(const QStringList &args, const QString &settingsIdHint) postCommand(cmd); } - loadPythonDumpers(); + if (attemptQuickStart()) { + postCommand("set auto-solib-add off", ConsoleCommand); + } else { + m_fullStartDone = true; + postCommand("set auto-solib-add on", ConsoleCommand); + loadPythonDumpers(); + } return true; } @@ -4929,8 +4923,7 @@ void GdbEngine::loadPythonDumpers() loadInitScript(); - postCommand("bbsetup", - ConsoleCommand, CB(handleHasPython)); + postCommand("bbsetup", ConsoleCommand, CB(handleHasPython)); } void GdbEngine::handleGdbError(QProcess::ProcessError error) @@ -5321,6 +5314,22 @@ void GdbEngine::requestDebugInformation(const DebugInfoTask &task) QProcess::startDetached(task.command); } +bool GdbEngine::attemptQuickStart() const +{ + // Don't try if the user does not ask for it. + if (!debuggerCore()->boolSetting(AttemptQuickStart)) + return false; + + // Don't try if there are breakpoints we might be able to handle. + BreakHandler *handler = breakHandler(); + foreach (BreakpointModelId id, handler->unclaimedBreakpointIds()) { + if (acceptsBreakpoint(id)) + return false; + } + + return true; +} + // // Factory // diff --git a/src/plugins/debugger/gdb/gdbengine.h b/src/plugins/debugger/gdb/gdbengine.h index c57d529dc50..8b2e3382eaf 100644 --- a/src/plugins/debugger/gdb/gdbengine.h +++ b/src/plugins/debugger/gdb/gdbengine.h @@ -420,9 +420,10 @@ private: ////////// Gdb Output, State & Capability Handling ////////// Q_SLOT void handleResponse(const QByteArray &buff); void handleStopResponse(const GdbMi &data); void handleResultRecord(GdbResponse *response); - void handleStop0(const GdbMi &data); void handleStop1(const GdbResponse &response); void handleStop1(const GdbMi &data); + void handleStop2(const GdbResponse &response); + void handleStop2(const GdbMi &data); Q_SLOT void handleStop2(); StackFrame parseStackFrame(const GdbMi &mi, int level); void resetCommandQueue(); @@ -746,6 +747,11 @@ private: ////////// View & Data Stuff ////////// friend class DebugInfoTaskHandler; void requestDebugInformation(const DebugInfoTask &task); DebugInfoTaskHandler *m_debugInfoTaskHandler; + + // Indicates whether we had at least one full attempt to load + // debug information. + bool attemptQuickStart() const; + bool m_fullStartDone; }; } // namespace Internal diff --git a/src/plugins/debugger/gdb/gdboptionspage.cpp b/src/plugins/debugger/gdb/gdboptionspage.cpp index 9eb7b8a75e5..bd378fe7ee2 100644 --- a/src/plugins/debugger/gdb/gdboptionspage.cpp +++ b/src/plugins/debugger/gdb/gdboptionspage.cpp @@ -73,6 +73,7 @@ public: QCheckBox *checkBoxBreakOnFatal; QCheckBox *checkBoxBreakOnRaise; QCheckBox *checkBoxEnableReverseDebugging; + QCheckBox *checkBoxAttemptQuickStart; QGroupBox *groupBoxStartupCommands; QTextEdit *textEditStartupCommands; @@ -176,6 +177,13 @@ public: "It exhibits unpredictable behavior when going backwards over system " "calls and is very likely to destroy your debugging session.

")); + checkBoxAttemptQuickStart = new QCheckBox(groupBoxGeneral); + checkBoxAttemptQuickStart->setText(GdbOptionsPage::tr("Attempt quick start")); + checkBoxAttemptQuickStart->setToolTip(GdbOptionsPage::tr("Checking this option " + "will postpone reading debug information as long as possible. This can result " + "in faster startup times at the price of not being able to set breakpoints " + "by file and number.")); + groupBoxStartupCommands = new QGroupBox(q); groupBoxStartupCommands->setTitle(GdbOptionsPage::tr("Additional Startup Commands")); @@ -223,6 +231,7 @@ public: formLayout->addRow(checkBoxBreakOnFatal); formLayout->addRow(checkBoxBreakOnRaise); formLayout->addRow(checkBoxEnableReverseDebugging); + formLayout->addRow(checkBoxAttemptQuickStart); QGridLayout *startLayout = new QGridLayout(groupBoxStartupCommands); startLayout->addWidget(textEditStartupCommands, 0, 0, 1, 1); @@ -302,6 +311,8 @@ QWidget *GdbOptionsPage::createPage(QWidget *parent) m_ui->checkBoxBreakOnRaise); m_group.insert(debuggerCore()->action(GdbWatchdogTimeout), m_ui->spinBoxGdbWatchdogTimeout); + m_group.insert(debuggerCore()->action(AttemptQuickStart), + m_ui->checkBoxAttemptQuickStart); m_group.insert(debuggerCore()->action(UseMessageBoxForSignals), m_ui->checkBoxUseMessageBoxForSignals); @@ -330,6 +341,7 @@ QWidget *GdbOptionsPage::createPage(QWidget *parent) << sep << m_ui->checkBoxSkipKnownFrames->text() << sep << m_ui->checkBoxUseMessageBoxForSignals->text() << sep << m_ui->checkBoxAdjustBreakpointLocations->text() + << sep << m_ui->checkBoxAttemptQuickStart->text() // << sep << m_ui->groupBoxPluginDebugging->title() // << sep << m_ui->radioButtonAllPluginBreakpoints->text() // << sep << m_ui->radioButtonSelectedPluginBreakpoints->text() diff --git a/tests/manual/debugger/simple/simple_test_app.cpp b/tests/manual/debugger/simple/simple_test_app.cpp index ca24206000e..4fb09301ebd 100644 --- a/tests/manual/debugger/simple/simple_test_app.cpp +++ b/tests/manual/debugger/simple/simple_test_app.cpp @@ -2048,7 +2048,7 @@ namespace final { // Continue. // Jump over next line. - return; + //return; while (a > 0) ++a; dummyStatement(&a);