From b439999f1d8e0d2dbb8c60bcffff8f21e7f80ac9 Mon Sep 17 00:00:00 2001 From: hjk Date: Tue, 17 Apr 2012 10:00:40 +0200 Subject: [PATCH] debugger: try quicker start when no breakpoints are set This prevents initial reading of debug information when no breakpoints are set. The debug information will be read on first stop instead, e.g. when the user interrupts. Change-Id: I6156347bf108e9ed89f54ca67021f37c02fa5116 Reviewed-by: Aurindam Jana --- src/plugins/debugger/debuggeractions.cpp | 6 ++ src/plugins/debugger/debuggeractions.h | 1 + src/plugins/debugger/gdb/attachgdbadapter.cpp | 2 +- src/plugins/debugger/gdb/gdbengine.cpp | 93 ++++++++++--------- src/plugins/debugger/gdb/gdbengine.h | 8 +- src/plugins/debugger/gdb/gdboptionspage.cpp | 12 +++ .../debugger/simple/simple_test_app.cpp | 2 +- 7 files changed, 79 insertions(+), 45 deletions(-) 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);