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 <aurindam.jana@nokia.com>
This commit is contained in:
hjk
2012-04-17 10:00:40 +02:00
committed by Aurindam Jana
parent 8209b9d9d5
commit b439999f1d
7 changed files with 79 additions and 45 deletions

View File

@@ -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"));

View File

@@ -118,6 +118,7 @@ enum DebuggerActionCode
// Gdb
LoadGdbInit,
AttemptQuickStart,
GdbStartupCommands,
GdbWatchdogTimeout,
AutoEnrichParameters,

View File

@@ -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)

View File

@@ -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<GdbMi>());
}
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<GdbMi>(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<GdbMi>());
handleStop2(response.cookie.value<GdbMi>());
}
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
//

View File

@@ -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

View File

@@ -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.</p><body></html>"));
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()

View File

@@ -2048,7 +2048,7 @@ namespace final {
// Continue.
// Jump over next line.
return;
//return;
while (a > 0)
++a;
dummyStatement(&a);